package it.tdlight.jni;

import java.io.ByteArrayOutputStream;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.nio.charset.StandardCharsets;
import java.io.IOException;
import java.io.DataInput;
import java.util.Arrays;
import java.util.Objects;

/**
 * This class contains as static nested classes all other TDLib interface
 * type-classes and function-classes.
 * <p>
 * It has no inner classes, functions or public members.
 */
public final class TdApi {

	private TdApi() {}

	/**
	 * This class is a base class for all TDLib interface classes.
	 */
	public abstract static class Object {

		/**
		 * Returns a string representation of the object.
		 *
		 * @return a string representation of the object.
		 */
		public native String toString();

		/**
		 * Returns an identifier uniquely determining type of the object.
		 *
		 * @return a unique identifier of the object type.
		 */
		public abstract int getConstructor();

		/**
		 * Default Object constructor.
		 */
		private Object() {}

		/**
		 * Serialize the object.
		 *
		 * @return the current object serialized into a byte[].
		 * @throws IOException the serialization failed
		 */
		public byte[] serialize() throws IOException {
			try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
				try (DataOutputStream out = new DataOutputStream(baos)) {
					serialize(out);
					return baos.toByteArray();
				}
			}
		}

		/**
		 * Serialize the object.
		 *
		 * @param out the output in which the object is serialized.
		 * @throws IOException the serialization failed
		 */
		public abstract void serialize(DataOutput out) throws IOException;

	}

	/**
	 * This class is a base class for all TDLib interface function-classes.
	 * @param <R> The function return type
	 */
	public abstract static class Function<R extends TdApi.Object> extends TdApi.Object {

		/**
		 * Default Function constructor.
		 */
		private Function() {}

		/**
		 * Returns a string representation of the object.
		 *
		 * @return a string representation of the object.
		 */
		public native String toString();

  }

	/**
	 * This class deserializes TDLib classes
	**/
	public static class Deserializer {

		/**
		 * The default constructor
		**/
		public Deserializer() {
		}

		/**
		 * Deserialize the TDLib class
		 * @param input stream that contain the serialized TDLib class to deserialize
		 * @return the deserialized TDLib class
		 * @throws IOException the deserialization failed
		**/
		public static Object deserialize(DataInput input) throws IOException {
			switch(input.readInt()) {
				case AccessHash.CONSTRUCTOR: return new AccessHash(input);
				case AccessHashTypeUser.CONSTRUCTOR: return new AccessHashTypeUser(input);
				case AccessHashTypeChannel.CONSTRUCTOR: return new AccessHashTypeChannel(input);
				case AccountTtl.CONSTRUCTOR: return new AccountTtl(input);
				case AddedReaction.CONSTRUCTOR: return new AddedReaction(input);
				case AddedReactions.CONSTRUCTOR: return new AddedReactions(input);
				case Address.CONSTRUCTOR: return new Address(input);
				case AnimatedChatPhoto.CONSTRUCTOR: return new AnimatedChatPhoto(input);
				case AnimatedEmoji.CONSTRUCTOR: return new AnimatedEmoji(input);
				case Animation.CONSTRUCTOR: return new Animation(input);
				case Animations.CONSTRUCTOR: return new Animations(input);
				case AttachmentMenuBot.CONSTRUCTOR: return new AttachmentMenuBot(input);
				case AttachmentMenuBotColor.CONSTRUCTOR: return new AttachmentMenuBotColor(input);
				case Audio.CONSTRUCTOR: return new Audio(input);
				case AuthenticationCodeInfo.CONSTRUCTOR: return new AuthenticationCodeInfo(input);
				case AuthenticationCodeTypeTelegramMessage.CONSTRUCTOR: return new AuthenticationCodeTypeTelegramMessage(input);
				case AuthenticationCodeTypeSms.CONSTRUCTOR: return new AuthenticationCodeTypeSms(input);
				case AuthenticationCodeTypeCall.CONSTRUCTOR: return new AuthenticationCodeTypeCall(input);
				case AuthenticationCodeTypeFlashCall.CONSTRUCTOR: return new AuthenticationCodeTypeFlashCall(input);
				case AuthenticationCodeTypeMissedCall.CONSTRUCTOR: return new AuthenticationCodeTypeMissedCall(input);
				case AuthenticationCodeTypeFragment.CONSTRUCTOR: return new AuthenticationCodeTypeFragment(input);
				case AuthenticationCodeTypeFirebaseAndroid.CONSTRUCTOR: return new AuthenticationCodeTypeFirebaseAndroid(input);
				case AuthenticationCodeTypeFirebaseIos.CONSTRUCTOR: return new AuthenticationCodeTypeFirebaseIos(input);
				case AuthorizationStateWaitTdlibParameters.CONSTRUCTOR: return new AuthorizationStateWaitTdlibParameters(input);
				case AuthorizationStateWaitPhoneNumber.CONSTRUCTOR: return new AuthorizationStateWaitPhoneNumber(input);
				case AuthorizationStateWaitEmailAddress.CONSTRUCTOR: return new AuthorizationStateWaitEmailAddress(input);
				case AuthorizationStateWaitEmailCode.CONSTRUCTOR: return new AuthorizationStateWaitEmailCode(input);
				case AuthorizationStateWaitCode.CONSTRUCTOR: return new AuthorizationStateWaitCode(input);
				case AuthorizationStateWaitOtherDeviceConfirmation.CONSTRUCTOR: return new AuthorizationStateWaitOtherDeviceConfirmation(input);
				case AuthorizationStateWaitRegistration.CONSTRUCTOR: return new AuthorizationStateWaitRegistration(input);
				case AuthorizationStateWaitPassword.CONSTRUCTOR: return new AuthorizationStateWaitPassword(input);
				case AuthorizationStateReady.CONSTRUCTOR: return new AuthorizationStateReady(input);
				case AuthorizationStateLoggingOut.CONSTRUCTOR: return new AuthorizationStateLoggingOut(input);
				case AuthorizationStateClosing.CONSTRUCTOR: return new AuthorizationStateClosing(input);
				case AuthorizationStateClosed.CONSTRUCTOR: return new AuthorizationStateClosed(input);
				case AutoDownloadSettings.CONSTRUCTOR: return new AutoDownloadSettings(input);
				case AutoDownloadSettingsPresets.CONSTRUCTOR: return new AutoDownloadSettingsPresets(input);
				case AutosaveSettings.CONSTRUCTOR: return new AutosaveSettings(input);
				case AutosaveSettingsException.CONSTRUCTOR: return new AutosaveSettingsException(input);
				case AutosaveSettingsScopePrivateChats.CONSTRUCTOR: return new AutosaveSettingsScopePrivateChats(input);
				case AutosaveSettingsScopeGroupChats.CONSTRUCTOR: return new AutosaveSettingsScopeGroupChats(input);
				case AutosaveSettingsScopeChannelChats.CONSTRUCTOR: return new AutosaveSettingsScopeChannelChats(input);
				case AutosaveSettingsScopeChat.CONSTRUCTOR: return new AutosaveSettingsScopeChat(input);
				case AvailableReaction.CONSTRUCTOR: return new AvailableReaction(input);
				case AvailableReactions.CONSTRUCTOR: return new AvailableReactions(input);
				case Background.CONSTRUCTOR: return new Background(input);
				case BackgroundFillSolid.CONSTRUCTOR: return new BackgroundFillSolid(input);
				case BackgroundFillGradient.CONSTRUCTOR: return new BackgroundFillGradient(input);
				case BackgroundFillFreeformGradient.CONSTRUCTOR: return new BackgroundFillFreeformGradient(input);
				case BackgroundTypeWallpaper.CONSTRUCTOR: return new BackgroundTypeWallpaper(input);
				case BackgroundTypePattern.CONSTRUCTOR: return new BackgroundTypePattern(input);
				case BackgroundTypeFill.CONSTRUCTOR: return new BackgroundTypeFill(input);
				case Backgrounds.CONSTRUCTOR: return new Backgrounds(input);
				case BankCardActionOpenUrl.CONSTRUCTOR: return new BankCardActionOpenUrl(input);
				case BankCardInfo.CONSTRUCTOR: return new BankCardInfo(input);
				case BasicGroup.CONSTRUCTOR: return new BasicGroup(input);
				case BasicGroupFullInfo.CONSTRUCTOR: return new BasicGroupFullInfo(input);
				case BotCommand.CONSTRUCTOR: return new BotCommand(input);
				case BotCommandScopeDefault.CONSTRUCTOR: return new BotCommandScopeDefault(input);
				case BotCommandScopeAllPrivateChats.CONSTRUCTOR: return new BotCommandScopeAllPrivateChats(input);
				case BotCommandScopeAllGroupChats.CONSTRUCTOR: return new BotCommandScopeAllGroupChats(input);
				case BotCommandScopeAllChatAdministrators.CONSTRUCTOR: return new BotCommandScopeAllChatAdministrators(input);
				case BotCommandScopeChat.CONSTRUCTOR: return new BotCommandScopeChat(input);
				case BotCommandScopeChatAdministrators.CONSTRUCTOR: return new BotCommandScopeChatAdministrators(input);
				case BotCommandScopeChatMember.CONSTRUCTOR: return new BotCommandScopeChatMember(input);
				case BotCommands.CONSTRUCTOR: return new BotCommands(input);
				case BotInfo.CONSTRUCTOR: return new BotInfo(input);
				case BotMenuButton.CONSTRUCTOR: return new BotMenuButton(input);
				case Call.CONSTRUCTOR: return new Call(input);
				case CallDiscardReasonEmpty.CONSTRUCTOR: return new CallDiscardReasonEmpty(input);
				case CallDiscardReasonMissed.CONSTRUCTOR: return new CallDiscardReasonMissed(input);
				case CallDiscardReasonDeclined.CONSTRUCTOR: return new CallDiscardReasonDeclined(input);
				case CallDiscardReasonDisconnected.CONSTRUCTOR: return new CallDiscardReasonDisconnected(input);
				case CallDiscardReasonHungUp.CONSTRUCTOR: return new CallDiscardReasonHungUp(input);
				case CallId.CONSTRUCTOR: return new CallId(input);
				case CallProblemEcho.CONSTRUCTOR: return new CallProblemEcho(input);
				case CallProblemNoise.CONSTRUCTOR: return new CallProblemNoise(input);
				case CallProblemInterruptions.CONSTRUCTOR: return new CallProblemInterruptions(input);
				case CallProblemDistortedSpeech.CONSTRUCTOR: return new CallProblemDistortedSpeech(input);
				case CallProblemSilentLocal.CONSTRUCTOR: return new CallProblemSilentLocal(input);
				case CallProblemSilentRemote.CONSTRUCTOR: return new CallProblemSilentRemote(input);
				case CallProblemDropped.CONSTRUCTOR: return new CallProblemDropped(input);
				case CallProblemDistortedVideo.CONSTRUCTOR: return new CallProblemDistortedVideo(input);
				case CallProblemPixelatedVideo.CONSTRUCTOR: return new CallProblemPixelatedVideo(input);
				case CallProtocol.CONSTRUCTOR: return new CallProtocol(input);
				case CallServer.CONSTRUCTOR: return new CallServer(input);
				case CallServerTypeTelegramReflector.CONSTRUCTOR: return new CallServerTypeTelegramReflector(input);
				case CallServerTypeWebrtc.CONSTRUCTOR: return new CallServerTypeWebrtc(input);
				case CallStatePending.CONSTRUCTOR: return new CallStatePending(input);
				case CallStateExchangingKeys.CONSTRUCTOR: return new CallStateExchangingKeys(input);
				case CallStateReady.CONSTRUCTOR: return new CallStateReady(input);
				case CallStateHangingUp.CONSTRUCTOR: return new CallStateHangingUp(input);
				case CallStateDiscarded.CONSTRUCTOR: return new CallStateDiscarded(input);
				case CallStateError.CONSTRUCTOR: return new CallStateError(input);
				case CallbackQueryAnswer.CONSTRUCTOR: return new CallbackQueryAnswer(input);
				case CallbackQueryPayloadData.CONSTRUCTOR: return new CallbackQueryPayloadData(input);
				case CallbackQueryPayloadDataWithPassword.CONSTRUCTOR: return new CallbackQueryPayloadDataWithPassword(input);
				case CallbackQueryPayloadGame.CONSTRUCTOR: return new CallbackQueryPayloadGame(input);
				case CanTransferOwnershipResultOk.CONSTRUCTOR: return new CanTransferOwnershipResultOk(input);
				case CanTransferOwnershipResultPasswordNeeded.CONSTRUCTOR: return new CanTransferOwnershipResultPasswordNeeded(input);
				case CanTransferOwnershipResultPasswordTooFresh.CONSTRUCTOR: return new CanTransferOwnershipResultPasswordTooFresh(input);
				case CanTransferOwnershipResultSessionTooFresh.CONSTRUCTOR: return new CanTransferOwnershipResultSessionTooFresh(input);
				case Chat.CONSTRUCTOR: return new Chat(input);
				case ChatActionTyping.CONSTRUCTOR: return new ChatActionTyping(input);
				case ChatActionRecordingVideo.CONSTRUCTOR: return new ChatActionRecordingVideo(input);
				case ChatActionUploadingVideo.CONSTRUCTOR: return new ChatActionUploadingVideo(input);
				case ChatActionRecordingVoiceNote.CONSTRUCTOR: return new ChatActionRecordingVoiceNote(input);
				case ChatActionUploadingVoiceNote.CONSTRUCTOR: return new ChatActionUploadingVoiceNote(input);
				case ChatActionUploadingPhoto.CONSTRUCTOR: return new ChatActionUploadingPhoto(input);
				case ChatActionUploadingDocument.CONSTRUCTOR: return new ChatActionUploadingDocument(input);
				case ChatActionChoosingSticker.CONSTRUCTOR: return new ChatActionChoosingSticker(input);
				case ChatActionChoosingLocation.CONSTRUCTOR: return new ChatActionChoosingLocation(input);
				case ChatActionChoosingContact.CONSTRUCTOR: return new ChatActionChoosingContact(input);
				case ChatActionStartPlayingGame.CONSTRUCTOR: return new ChatActionStartPlayingGame(input);
				case ChatActionRecordingVideoNote.CONSTRUCTOR: return new ChatActionRecordingVideoNote(input);
				case ChatActionUploadingVideoNote.CONSTRUCTOR: return new ChatActionUploadingVideoNote(input);
				case ChatActionWatchingAnimations.CONSTRUCTOR: return new ChatActionWatchingAnimations(input);
				case ChatActionCancel.CONSTRUCTOR: return new ChatActionCancel(input);
				case ChatActionBarReportSpam.CONSTRUCTOR: return new ChatActionBarReportSpam(input);
				case ChatActionBarReportUnrelatedLocation.CONSTRUCTOR: return new ChatActionBarReportUnrelatedLocation(input);
				case ChatActionBarInviteMembers.CONSTRUCTOR: return new ChatActionBarInviteMembers(input);
				case ChatActionBarReportAddBlock.CONSTRUCTOR: return new ChatActionBarReportAddBlock(input);
				case ChatActionBarAddContact.CONSTRUCTOR: return new ChatActionBarAddContact(input);
				case ChatActionBarSharePhoneNumber.CONSTRUCTOR: return new ChatActionBarSharePhoneNumber(input);
				case ChatActionBarJoinRequest.CONSTRUCTOR: return new ChatActionBarJoinRequest(input);
				case ChatAdministrator.CONSTRUCTOR: return new ChatAdministrator(input);
				case ChatAdministratorRights.CONSTRUCTOR: return new ChatAdministratorRights(input);
				case ChatAdministrators.CONSTRUCTOR: return new ChatAdministrators(input);
				case ChatAvailableReactionsAll.CONSTRUCTOR: return new ChatAvailableReactionsAll(input);
				case ChatAvailableReactionsSome.CONSTRUCTOR: return new ChatAvailableReactionsSome(input);
				case ChatBackground.CONSTRUCTOR: return new ChatBackground(input);
				case ChatEvent.CONSTRUCTOR: return new ChatEvent(input);
				case ChatEventMessageEdited.CONSTRUCTOR: return new ChatEventMessageEdited(input);
				case ChatEventMessageDeleted.CONSTRUCTOR: return new ChatEventMessageDeleted(input);
				case ChatEventMessagePinned.CONSTRUCTOR: return new ChatEventMessagePinned(input);
				case ChatEventMessageUnpinned.CONSTRUCTOR: return new ChatEventMessageUnpinned(input);
				case ChatEventPollStopped.CONSTRUCTOR: return new ChatEventPollStopped(input);
				case ChatEventMemberJoined.CONSTRUCTOR: return new ChatEventMemberJoined(input);
				case ChatEventMemberJoinedByInviteLink.CONSTRUCTOR: return new ChatEventMemberJoinedByInviteLink(input);
				case ChatEventMemberJoinedByRequest.CONSTRUCTOR: return new ChatEventMemberJoinedByRequest(input);
				case ChatEventMemberInvited.CONSTRUCTOR: return new ChatEventMemberInvited(input);
				case ChatEventMemberLeft.CONSTRUCTOR: return new ChatEventMemberLeft(input);
				case ChatEventMemberPromoted.CONSTRUCTOR: return new ChatEventMemberPromoted(input);
				case ChatEventMemberRestricted.CONSTRUCTOR: return new ChatEventMemberRestricted(input);
				case ChatEventAvailableReactionsChanged.CONSTRUCTOR: return new ChatEventAvailableReactionsChanged(input);
				case ChatEventDescriptionChanged.CONSTRUCTOR: return new ChatEventDescriptionChanged(input);
				case ChatEventLinkedChatChanged.CONSTRUCTOR: return new ChatEventLinkedChatChanged(input);
				case ChatEventLocationChanged.CONSTRUCTOR: return new ChatEventLocationChanged(input);
				case ChatEventMessageAutoDeleteTimeChanged.CONSTRUCTOR: return new ChatEventMessageAutoDeleteTimeChanged(input);
				case ChatEventPermissionsChanged.CONSTRUCTOR: return new ChatEventPermissionsChanged(input);
				case ChatEventPhotoChanged.CONSTRUCTOR: return new ChatEventPhotoChanged(input);
				case ChatEventSlowModeDelayChanged.CONSTRUCTOR: return new ChatEventSlowModeDelayChanged(input);
				case ChatEventStickerSetChanged.CONSTRUCTOR: return new ChatEventStickerSetChanged(input);
				case ChatEventTitleChanged.CONSTRUCTOR: return new ChatEventTitleChanged(input);
				case ChatEventUsernameChanged.CONSTRUCTOR: return new ChatEventUsernameChanged(input);
				case ChatEventActiveUsernamesChanged.CONSTRUCTOR: return new ChatEventActiveUsernamesChanged(input);
				case ChatEventHasProtectedContentToggled.CONSTRUCTOR: return new ChatEventHasProtectedContentToggled(input);
				case ChatEventInvitesToggled.CONSTRUCTOR: return new ChatEventInvitesToggled(input);
				case ChatEventIsAllHistoryAvailableToggled.CONSTRUCTOR: return new ChatEventIsAllHistoryAvailableToggled(input);
				case ChatEventHasAggressiveAntiSpamEnabledToggled.CONSTRUCTOR: return new ChatEventHasAggressiveAntiSpamEnabledToggled(input);
				case ChatEventSignMessagesToggled.CONSTRUCTOR: return new ChatEventSignMessagesToggled(input);
				case ChatEventInviteLinkEdited.CONSTRUCTOR: return new ChatEventInviteLinkEdited(input);
				case ChatEventInviteLinkRevoked.CONSTRUCTOR: return new ChatEventInviteLinkRevoked(input);
				case ChatEventInviteLinkDeleted.CONSTRUCTOR: return new ChatEventInviteLinkDeleted(input);
				case ChatEventVideoChatCreated.CONSTRUCTOR: return new ChatEventVideoChatCreated(input);
				case ChatEventVideoChatEnded.CONSTRUCTOR: return new ChatEventVideoChatEnded(input);
				case ChatEventVideoChatMuteNewParticipantsToggled.CONSTRUCTOR: return new ChatEventVideoChatMuteNewParticipantsToggled(input);
				case ChatEventVideoChatParticipantIsMutedToggled.CONSTRUCTOR: return new ChatEventVideoChatParticipantIsMutedToggled(input);
				case ChatEventVideoChatParticipantVolumeLevelChanged.CONSTRUCTOR: return new ChatEventVideoChatParticipantVolumeLevelChanged(input);
				case ChatEventIsForumToggled.CONSTRUCTOR: return new ChatEventIsForumToggled(input);
				case ChatEventForumTopicCreated.CONSTRUCTOR: return new ChatEventForumTopicCreated(input);
				case ChatEventForumTopicEdited.CONSTRUCTOR: return new ChatEventForumTopicEdited(input);
				case ChatEventForumTopicToggleIsClosed.CONSTRUCTOR: return new ChatEventForumTopicToggleIsClosed(input);
				case ChatEventForumTopicToggleIsHidden.CONSTRUCTOR: return new ChatEventForumTopicToggleIsHidden(input);
				case ChatEventForumTopicDeleted.CONSTRUCTOR: return new ChatEventForumTopicDeleted(input);
				case ChatEventForumTopicPinned.CONSTRUCTOR: return new ChatEventForumTopicPinned(input);
				case ChatEventLogFilters.CONSTRUCTOR: return new ChatEventLogFilters(input);
				case ChatEvents.CONSTRUCTOR: return new ChatEvents(input);
				case ChatFolder.CONSTRUCTOR: return new ChatFolder(input);
				case ChatFolderIcon.CONSTRUCTOR: return new ChatFolderIcon(input);
				case ChatFolderInfo.CONSTRUCTOR: return new ChatFolderInfo(input);
				case ChatFolderInviteLink.CONSTRUCTOR: return new ChatFolderInviteLink(input);
				case ChatFolderInviteLinkInfo.CONSTRUCTOR: return new ChatFolderInviteLinkInfo(input);
				case ChatFolderInviteLinks.CONSTRUCTOR: return new ChatFolderInviteLinks(input);
				case ChatInviteLink.CONSTRUCTOR: return new ChatInviteLink(input);
				case ChatInviteLinkCount.CONSTRUCTOR: return new ChatInviteLinkCount(input);
				case ChatInviteLinkCounts.CONSTRUCTOR: return new ChatInviteLinkCounts(input);
				case ChatInviteLinkInfo.CONSTRUCTOR: return new ChatInviteLinkInfo(input);
				case ChatInviteLinkMember.CONSTRUCTOR: return new ChatInviteLinkMember(input);
				case ChatInviteLinkMembers.CONSTRUCTOR: return new ChatInviteLinkMembers(input);
				case ChatInviteLinks.CONSTRUCTOR: return new ChatInviteLinks(input);
				case ChatJoinRequest.CONSTRUCTOR: return new ChatJoinRequest(input);
				case ChatJoinRequests.CONSTRUCTOR: return new ChatJoinRequests(input);
				case ChatJoinRequestsInfo.CONSTRUCTOR: return new ChatJoinRequestsInfo(input);
				case ChatListMain.CONSTRUCTOR: return new ChatListMain(input);
				case ChatListArchive.CONSTRUCTOR: return new ChatListArchive(input);
				case ChatListFolder.CONSTRUCTOR: return new ChatListFolder(input);
				case ChatLists.CONSTRUCTOR: return new ChatLists(input);
				case ChatLocation.CONSTRUCTOR: return new ChatLocation(input);
				case ChatMember.CONSTRUCTOR: return new ChatMember(input);
				case ChatMemberStatusCreator.CONSTRUCTOR: return new ChatMemberStatusCreator(input);
				case ChatMemberStatusAdministrator.CONSTRUCTOR: return new ChatMemberStatusAdministrator(input);
				case ChatMemberStatusMember.CONSTRUCTOR: return new ChatMemberStatusMember(input);
				case ChatMemberStatusRestricted.CONSTRUCTOR: return new ChatMemberStatusRestricted(input);
				case ChatMemberStatusLeft.CONSTRUCTOR: return new ChatMemberStatusLeft(input);
				case ChatMemberStatusBanned.CONSTRUCTOR: return new ChatMemberStatusBanned(input);
				case ChatMembers.CONSTRUCTOR: return new ChatMembers(input);
				case ChatMembersFilterContacts.CONSTRUCTOR: return new ChatMembersFilterContacts(input);
				case ChatMembersFilterAdministrators.CONSTRUCTOR: return new ChatMembersFilterAdministrators(input);
				case ChatMembersFilterMembers.CONSTRUCTOR: return new ChatMembersFilterMembers(input);
				case ChatMembersFilterMention.CONSTRUCTOR: return new ChatMembersFilterMention(input);
				case ChatMembersFilterRestricted.CONSTRUCTOR: return new ChatMembersFilterRestricted(input);
				case ChatMembersFilterBanned.CONSTRUCTOR: return new ChatMembersFilterBanned(input);
				case ChatMembersFilterBots.CONSTRUCTOR: return new ChatMembersFilterBots(input);
				case ChatMessageSender.CONSTRUCTOR: return new ChatMessageSender(input);
				case ChatMessageSenders.CONSTRUCTOR: return new ChatMessageSenders(input);
				case ChatNearby.CONSTRUCTOR: return new ChatNearby(input);
				case ChatNotificationSettings.CONSTRUCTOR: return new ChatNotificationSettings(input);
				case ChatPermissions.CONSTRUCTOR: return new ChatPermissions(input);
				case ChatPhoto.CONSTRUCTOR: return new ChatPhoto(input);
				case ChatPhotoInfo.CONSTRUCTOR: return new ChatPhotoInfo(input);
				case ChatPhotoSticker.CONSTRUCTOR: return new ChatPhotoSticker(input);
				case ChatPhotoStickerTypeRegularOrMask.CONSTRUCTOR: return new ChatPhotoStickerTypeRegularOrMask(input);
				case ChatPhotoStickerTypeCustomEmoji.CONSTRUCTOR: return new ChatPhotoStickerTypeCustomEmoji(input);
				case ChatPhotos.CONSTRUCTOR: return new ChatPhotos(input);
				case ChatPosition.CONSTRUCTOR: return new ChatPosition(input);
				case ChatReportReasonSpam.CONSTRUCTOR: return new ChatReportReasonSpam(input);
				case ChatReportReasonViolence.CONSTRUCTOR: return new ChatReportReasonViolence(input);
				case ChatReportReasonPornography.CONSTRUCTOR: return new ChatReportReasonPornography(input);
				case ChatReportReasonChildAbuse.CONSTRUCTOR: return new ChatReportReasonChildAbuse(input);
				case ChatReportReasonCopyright.CONSTRUCTOR: return new ChatReportReasonCopyright(input);
				case ChatReportReasonUnrelatedLocation.CONSTRUCTOR: return new ChatReportReasonUnrelatedLocation(input);
				case ChatReportReasonFake.CONSTRUCTOR: return new ChatReportReasonFake(input);
				case ChatReportReasonIllegalDrugs.CONSTRUCTOR: return new ChatReportReasonIllegalDrugs(input);
				case ChatReportReasonPersonalDetails.CONSTRUCTOR: return new ChatReportReasonPersonalDetails(input);
				case ChatReportReasonCustom.CONSTRUCTOR: return new ChatReportReasonCustom(input);
				case ChatSourceMtprotoProxy.CONSTRUCTOR: return new ChatSourceMtprotoProxy(input);
				case ChatSourcePublicServiceAnnouncement.CONSTRUCTOR: return new ChatSourcePublicServiceAnnouncement(input);
				case ChatStatisticsSupergroup.CONSTRUCTOR: return new ChatStatisticsSupergroup(input);
				case ChatStatisticsChannel.CONSTRUCTOR: return new ChatStatisticsChannel(input);
				case ChatStatisticsAdministratorActionsInfo.CONSTRUCTOR: return new ChatStatisticsAdministratorActionsInfo(input);
				case ChatStatisticsInviterInfo.CONSTRUCTOR: return new ChatStatisticsInviterInfo(input);
				case ChatStatisticsMessageInteractionInfo.CONSTRUCTOR: return new ChatStatisticsMessageInteractionInfo(input);
				case ChatStatisticsMessageSenderInfo.CONSTRUCTOR: return new ChatStatisticsMessageSenderInfo(input);
				case ChatTheme.CONSTRUCTOR: return new ChatTheme(input);
				case ChatTypePrivate.CONSTRUCTOR: return new ChatTypePrivate(input);
				case ChatTypeBasicGroup.CONSTRUCTOR: return new ChatTypeBasicGroup(input);
				case ChatTypeSupergroup.CONSTRUCTOR: return new ChatTypeSupergroup(input);
				case ChatTypeSecret.CONSTRUCTOR: return new ChatTypeSecret(input);
				case Chats.CONSTRUCTOR: return new Chats(input);
				case ChatsNearby.CONSTRUCTOR: return new ChatsNearby(input);
				case CheckChatUsernameResultOk.CONSTRUCTOR: return new CheckChatUsernameResultOk(input);
				case CheckChatUsernameResultUsernameInvalid.CONSTRUCTOR: return new CheckChatUsernameResultUsernameInvalid(input);
				case CheckChatUsernameResultUsernameOccupied.CONSTRUCTOR: return new CheckChatUsernameResultUsernameOccupied(input);
				case CheckChatUsernameResultUsernamePurchasable.CONSTRUCTOR: return new CheckChatUsernameResultUsernamePurchasable(input);
				case CheckChatUsernameResultPublicChatsTooMany.CONSTRUCTOR: return new CheckChatUsernameResultPublicChatsTooMany(input);
				case CheckChatUsernameResultPublicGroupsUnavailable.CONSTRUCTOR: return new CheckChatUsernameResultPublicGroupsUnavailable(input);
				case CheckStickerSetNameResultOk.CONSTRUCTOR: return new CheckStickerSetNameResultOk(input);
				case CheckStickerSetNameResultNameInvalid.CONSTRUCTOR: return new CheckStickerSetNameResultNameInvalid(input);
				case CheckStickerSetNameResultNameOccupied.CONSTRUCTOR: return new CheckStickerSetNameResultNameOccupied(input);
				case ClosedVectorPath.CONSTRUCTOR: return new ClosedVectorPath(input);
				case ConnectedWebsite.CONSTRUCTOR: return new ConnectedWebsite(input);
				case ConnectedWebsites.CONSTRUCTOR: return new ConnectedWebsites(input);
				case ConnectionStateWaitingForNetwork.CONSTRUCTOR: return new ConnectionStateWaitingForNetwork(input);
				case ConnectionStateConnectingToProxy.CONSTRUCTOR: return new ConnectionStateConnectingToProxy(input);
				case ConnectionStateConnecting.CONSTRUCTOR: return new ConnectionStateConnecting(input);
				case ConnectionStateUpdating.CONSTRUCTOR: return new ConnectionStateUpdating(input);
				case ConnectionStateReady.CONSTRUCTOR: return new ConnectionStateReady(input);
				case Contact.CONSTRUCTOR: return new Contact(input);
				case Count.CONSTRUCTOR: return new Count(input);
				case Countries.CONSTRUCTOR: return new Countries(input);
				case CountryInfo.CONSTRUCTOR: return new CountryInfo(input);
				case CustomRequestResult.CONSTRUCTOR: return new CustomRequestResult(input);
				case DatabaseStatistics.CONSTRUCTOR: return new DatabaseStatistics(input);
				case Date.CONSTRUCTOR: return new Date(input);
				case DateRange.CONSTRUCTOR: return new DateRange(input);
				case DatedFile.CONSTRUCTOR: return new DatedFile(input);
				case DeepLinkInfo.CONSTRUCTOR: return new DeepLinkInfo(input);
				case DeviceTokenFirebaseCloudMessaging.CONSTRUCTOR: return new DeviceTokenFirebaseCloudMessaging(input);
				case DeviceTokenApplePush.CONSTRUCTOR: return new DeviceTokenApplePush(input);
				case DeviceTokenApplePushVoIP.CONSTRUCTOR: return new DeviceTokenApplePushVoIP(input);
				case DeviceTokenWindowsPush.CONSTRUCTOR: return new DeviceTokenWindowsPush(input);
				case DeviceTokenMicrosoftPush.CONSTRUCTOR: return new DeviceTokenMicrosoftPush(input);
				case DeviceTokenMicrosoftPushVoIP.CONSTRUCTOR: return new DeviceTokenMicrosoftPushVoIP(input);
				case DeviceTokenWebPush.CONSTRUCTOR: return new DeviceTokenWebPush(input);
				case DeviceTokenSimplePush.CONSTRUCTOR: return new DeviceTokenSimplePush(input);
				case DeviceTokenUbuntuPush.CONSTRUCTOR: return new DeviceTokenUbuntuPush(input);
				case DeviceTokenBlackBerryPush.CONSTRUCTOR: return new DeviceTokenBlackBerryPush(input);
				case DeviceTokenTizenPush.CONSTRUCTOR: return new DeviceTokenTizenPush(input);
				case DeviceTokenHuaweiPush.CONSTRUCTOR: return new DeviceTokenHuaweiPush(input);
				case DiceStickersRegular.CONSTRUCTOR: return new DiceStickersRegular(input);
				case DiceStickersSlotMachine.CONSTRUCTOR: return new DiceStickersSlotMachine(input);
				case Document.CONSTRUCTOR: return new Document(input);
				case DownloadedFileCounts.CONSTRUCTOR: return new DownloadedFileCounts(input);
				case DraftMessage.CONSTRUCTOR: return new DraftMessage(input);
				case EmailAddressAuthenticationCode.CONSTRUCTOR: return new EmailAddressAuthenticationCode(input);
				case EmailAddressAuthenticationAppleId.CONSTRUCTOR: return new EmailAddressAuthenticationAppleId(input);
				case EmailAddressAuthenticationGoogleId.CONSTRUCTOR: return new EmailAddressAuthenticationGoogleId(input);
				case EmailAddressAuthenticationCodeInfo.CONSTRUCTOR: return new EmailAddressAuthenticationCodeInfo(input);
				case EmailAddressResetStateAvailable.CONSTRUCTOR: return new EmailAddressResetStateAvailable(input);
				case EmailAddressResetStatePending.CONSTRUCTOR: return new EmailAddressResetStatePending(input);
				case EmojiCategories.CONSTRUCTOR: return new EmojiCategories(input);
				case EmojiCategory.CONSTRUCTOR: return new EmojiCategory(input);
				case EmojiCategoryTypeDefault.CONSTRUCTOR: return new EmojiCategoryTypeDefault(input);
				case EmojiCategoryTypeEmojiStatus.CONSTRUCTOR: return new EmojiCategoryTypeEmojiStatus(input);
				case EmojiCategoryTypeChatPhoto.CONSTRUCTOR: return new EmojiCategoryTypeChatPhoto(input);
				case EmojiReaction.CONSTRUCTOR: return new EmojiReaction(input);
				case EmojiStatus.CONSTRUCTOR: return new EmojiStatus(input);
				case EmojiStatuses.CONSTRUCTOR: return new EmojiStatuses(input);
				case Emojis.CONSTRUCTOR: return new Emojis(input);
				case EncryptedCredentials.CONSTRUCTOR: return new EncryptedCredentials(input);
				case EncryptedPassportElement.CONSTRUCTOR: return new EncryptedPassportElement(input);
				case Error.CONSTRUCTOR: return new Error(input);
				case File.CONSTRUCTOR: return new File(input);
				case FileDownload.CONSTRUCTOR: return new FileDownload(input);
				case FileDownloadedPrefixSize.CONSTRUCTOR: return new FileDownloadedPrefixSize(input);
				case FilePart.CONSTRUCTOR: return new FilePart(input);
				case FileTypeNone.CONSTRUCTOR: return new FileTypeNone(input);
				case FileTypeAnimation.CONSTRUCTOR: return new FileTypeAnimation(input);
				case FileTypeAudio.CONSTRUCTOR: return new FileTypeAudio(input);
				case FileTypeDocument.CONSTRUCTOR: return new FileTypeDocument(input);
				case FileTypeNotificationSound.CONSTRUCTOR: return new FileTypeNotificationSound(input);
				case FileTypePhoto.CONSTRUCTOR: return new FileTypePhoto(input);
				case FileTypeProfilePhoto.CONSTRUCTOR: return new FileTypeProfilePhoto(input);
				case FileTypeSecret.CONSTRUCTOR: return new FileTypeSecret(input);
				case FileTypeSecretThumbnail.CONSTRUCTOR: return new FileTypeSecretThumbnail(input);
				case FileTypeSecure.CONSTRUCTOR: return new FileTypeSecure(input);
				case FileTypeSticker.CONSTRUCTOR: return new FileTypeSticker(input);
				case FileTypeThumbnail.CONSTRUCTOR: return new FileTypeThumbnail(input);
				case FileTypeUnknown.CONSTRUCTOR: return new FileTypeUnknown(input);
				case FileTypeVideo.CONSTRUCTOR: return new FileTypeVideo(input);
				case FileTypeVideoNote.CONSTRUCTOR: return new FileTypeVideoNote(input);
				case FileTypeVoiceNote.CONSTRUCTOR: return new FileTypeVoiceNote(input);
				case FileTypeWallpaper.CONSTRUCTOR: return new FileTypeWallpaper(input);
				case FirebaseAuthenticationSettingsAndroid.CONSTRUCTOR: return new FirebaseAuthenticationSettingsAndroid(input);
				case FirebaseAuthenticationSettingsIos.CONSTRUCTOR: return new FirebaseAuthenticationSettingsIos(input);
				case FormattedText.CONSTRUCTOR: return new FormattedText(input);
				case ForumTopic.CONSTRUCTOR: return new ForumTopic(input);
				case ForumTopicIcon.CONSTRUCTOR: return new ForumTopicIcon(input);
				case ForumTopicInfo.CONSTRUCTOR: return new ForumTopicInfo(input);
				case ForumTopics.CONSTRUCTOR: return new ForumTopics(input);
				case FoundChatMessages.CONSTRUCTOR: return new FoundChatMessages(input);
				case FoundFileDownloads.CONSTRUCTOR: return new FoundFileDownloads(input);
				case FoundMessages.CONSTRUCTOR: return new FoundMessages(input);
				case FoundWebApp.CONSTRUCTOR: return new FoundWebApp(input);
				case Game.CONSTRUCTOR: return new Game(input);
				case GameHighScore.CONSTRUCTOR: return new GameHighScore(input);
				case GameHighScores.CONSTRUCTOR: return new GameHighScores(input);
				case GroupCall.CONSTRUCTOR: return new GroupCall(input);
				case GroupCallId.CONSTRUCTOR: return new GroupCallId(input);
				case GroupCallParticipant.CONSTRUCTOR: return new GroupCallParticipant(input);
				case GroupCallParticipantVideoInfo.CONSTRUCTOR: return new GroupCallParticipantVideoInfo(input);
				case GroupCallRecentSpeaker.CONSTRUCTOR: return new GroupCallRecentSpeaker(input);
				case GroupCallStream.CONSTRUCTOR: return new GroupCallStream(input);
				case GroupCallStreams.CONSTRUCTOR: return new GroupCallStreams(input);
				case GroupCallVideoQualityThumbnail.CONSTRUCTOR: return new GroupCallVideoQualityThumbnail(input);
				case GroupCallVideoQualityMedium.CONSTRUCTOR: return new GroupCallVideoQualityMedium(input);
				case GroupCallVideoQualityFull.CONSTRUCTOR: return new GroupCallVideoQualityFull(input);
				case GroupCallVideoSourceGroup.CONSTRUCTOR: return new GroupCallVideoSourceGroup(input);
				case Hashtags.CONSTRUCTOR: return new Hashtags(input);
				case HttpUrl.CONSTRUCTOR: return new HttpUrl(input);
				case IdentityDocument.CONSTRUCTOR: return new IdentityDocument(input);
				case ImportedContacts.CONSTRUCTOR: return new ImportedContacts(input);
				case InlineKeyboardButton.CONSTRUCTOR: return new InlineKeyboardButton(input);
				case InlineKeyboardButtonTypeUrl.CONSTRUCTOR: return new InlineKeyboardButtonTypeUrl(input);
				case InlineKeyboardButtonTypeLoginUrl.CONSTRUCTOR: return new InlineKeyboardButtonTypeLoginUrl(input);
				case InlineKeyboardButtonTypeWebApp.CONSTRUCTOR: return new InlineKeyboardButtonTypeWebApp(input);
				case InlineKeyboardButtonTypeCallback.CONSTRUCTOR: return new InlineKeyboardButtonTypeCallback(input);
				case InlineKeyboardButtonTypeCallbackWithPassword.CONSTRUCTOR: return new InlineKeyboardButtonTypeCallbackWithPassword(input);
				case InlineKeyboardButtonTypeCallbackGame.CONSTRUCTOR: return new InlineKeyboardButtonTypeCallbackGame(input);
				case InlineKeyboardButtonTypeSwitchInline.CONSTRUCTOR: return new InlineKeyboardButtonTypeSwitchInline(input);
				case InlineKeyboardButtonTypeBuy.CONSTRUCTOR: return new InlineKeyboardButtonTypeBuy(input);
				case InlineKeyboardButtonTypeUser.CONSTRUCTOR: return new InlineKeyboardButtonTypeUser(input);
				case InlineQueryResultArticle.CONSTRUCTOR: return new InlineQueryResultArticle(input);
				case InlineQueryResultContact.CONSTRUCTOR: return new InlineQueryResultContact(input);
				case InlineQueryResultLocation.CONSTRUCTOR: return new InlineQueryResultLocation(input);
				case InlineQueryResultVenue.CONSTRUCTOR: return new InlineQueryResultVenue(input);
				case InlineQueryResultGame.CONSTRUCTOR: return new InlineQueryResultGame(input);
				case InlineQueryResultAnimation.CONSTRUCTOR: return new InlineQueryResultAnimation(input);
				case InlineQueryResultAudio.CONSTRUCTOR: return new InlineQueryResultAudio(input);
				case InlineQueryResultDocument.CONSTRUCTOR: return new InlineQueryResultDocument(input);
				case InlineQueryResultPhoto.CONSTRUCTOR: return new InlineQueryResultPhoto(input);
				case InlineQueryResultSticker.CONSTRUCTOR: return new InlineQueryResultSticker(input);
				case InlineQueryResultVideo.CONSTRUCTOR: return new InlineQueryResultVideo(input);
				case InlineQueryResultVoiceNote.CONSTRUCTOR: return new InlineQueryResultVoiceNote(input);
				case InlineQueryResults.CONSTRUCTOR: return new InlineQueryResults(input);
				case InlineQueryResultsButton.CONSTRUCTOR: return new InlineQueryResultsButton(input);
				case InlineQueryResultsButtonTypeStartBot.CONSTRUCTOR: return new InlineQueryResultsButtonTypeStartBot(input);
				case InlineQueryResultsButtonTypeWebApp.CONSTRUCTOR: return new InlineQueryResultsButtonTypeWebApp(input);
				case InputBackgroundLocal.CONSTRUCTOR: return new InputBackgroundLocal(input);
				case InputBackgroundRemote.CONSTRUCTOR: return new InputBackgroundRemote(input);
				case InputBackgroundPrevious.CONSTRUCTOR: return new InputBackgroundPrevious(input);
				case InputChatPhotoPrevious.CONSTRUCTOR: return new InputChatPhotoPrevious(input);
				case InputChatPhotoStatic.CONSTRUCTOR: return new InputChatPhotoStatic(input);
				case InputChatPhotoAnimation.CONSTRUCTOR: return new InputChatPhotoAnimation(input);
				case InputChatPhotoSticker.CONSTRUCTOR: return new InputChatPhotoSticker(input);
				case InputCredentialsSaved.CONSTRUCTOR: return new InputCredentialsSaved(input);
				case InputCredentialsNew.CONSTRUCTOR: return new InputCredentialsNew(input);
				case InputCredentialsApplePay.CONSTRUCTOR: return new InputCredentialsApplePay(input);
				case InputCredentialsGooglePay.CONSTRUCTOR: return new InputCredentialsGooglePay(input);
				case InputFileId.CONSTRUCTOR: return new InputFileId(input);
				case InputFileRemote.CONSTRUCTOR: return new InputFileRemote(input);
				case InputFileLocal.CONSTRUCTOR: return new InputFileLocal(input);
				case InputFileGenerated.CONSTRUCTOR: return new InputFileGenerated(input);
				case InputIdentityDocument.CONSTRUCTOR: return new InputIdentityDocument(input);
				case InputInlineQueryResultAnimation.CONSTRUCTOR: return new InputInlineQueryResultAnimation(input);
				case InputInlineQueryResultArticle.CONSTRUCTOR: return new InputInlineQueryResultArticle(input);
				case InputInlineQueryResultAudio.CONSTRUCTOR: return new InputInlineQueryResultAudio(input);
				case InputInlineQueryResultContact.CONSTRUCTOR: return new InputInlineQueryResultContact(input);
				case InputInlineQueryResultDocument.CONSTRUCTOR: return new InputInlineQueryResultDocument(input);
				case InputInlineQueryResultGame.CONSTRUCTOR: return new InputInlineQueryResultGame(input);
				case InputInlineQueryResultLocation.CONSTRUCTOR: return new InputInlineQueryResultLocation(input);
				case InputInlineQueryResultPhoto.CONSTRUCTOR: return new InputInlineQueryResultPhoto(input);
				case InputInlineQueryResultSticker.CONSTRUCTOR: return new InputInlineQueryResultSticker(input);
				case InputInlineQueryResultVenue.CONSTRUCTOR: return new InputInlineQueryResultVenue(input);
				case InputInlineQueryResultVideo.CONSTRUCTOR: return new InputInlineQueryResultVideo(input);
				case InputInlineQueryResultVoiceNote.CONSTRUCTOR: return new InputInlineQueryResultVoiceNote(input);
				case InputInvoiceMessage.CONSTRUCTOR: return new InputInvoiceMessage(input);
				case InputInvoiceName.CONSTRUCTOR: return new InputInvoiceName(input);
				case InputMessageText.CONSTRUCTOR: return new InputMessageText(input);
				case InputMessageAnimation.CONSTRUCTOR: return new InputMessageAnimation(input);
				case InputMessageAudio.CONSTRUCTOR: return new InputMessageAudio(input);
				case InputMessageDocument.CONSTRUCTOR: return new InputMessageDocument(input);
				case InputMessagePhoto.CONSTRUCTOR: return new InputMessagePhoto(input);
				case InputMessageSticker.CONSTRUCTOR: return new InputMessageSticker(input);
				case InputMessageVideo.CONSTRUCTOR: return new InputMessageVideo(input);
				case InputMessageVideoNote.CONSTRUCTOR: return new InputMessageVideoNote(input);
				case InputMessageVoiceNote.CONSTRUCTOR: return new InputMessageVoiceNote(input);
				case InputMessageLocation.CONSTRUCTOR: return new InputMessageLocation(input);
				case InputMessageVenue.CONSTRUCTOR: return new InputMessageVenue(input);
				case InputMessageContact.CONSTRUCTOR: return new InputMessageContact(input);
				case InputMessageDice.CONSTRUCTOR: return new InputMessageDice(input);
				case InputMessageGame.CONSTRUCTOR: return new InputMessageGame(input);
				case InputMessageInvoice.CONSTRUCTOR: return new InputMessageInvoice(input);
				case InputMessagePoll.CONSTRUCTOR: return new InputMessagePoll(input);
				case InputMessageForwarded.CONSTRUCTOR: return new InputMessageForwarded(input);
				case InputPassportElementPersonalDetails.CONSTRUCTOR: return new InputPassportElementPersonalDetails(input);
				case InputPassportElementPassport.CONSTRUCTOR: return new InputPassportElementPassport(input);
				case InputPassportElementDriverLicense.CONSTRUCTOR: return new InputPassportElementDriverLicense(input);
				case InputPassportElementIdentityCard.CONSTRUCTOR: return new InputPassportElementIdentityCard(input);
				case InputPassportElementInternalPassport.CONSTRUCTOR: return new InputPassportElementInternalPassport(input);
				case InputPassportElementAddress.CONSTRUCTOR: return new InputPassportElementAddress(input);
				case InputPassportElementUtilityBill.CONSTRUCTOR: return new InputPassportElementUtilityBill(input);
				case InputPassportElementBankStatement.CONSTRUCTOR: return new InputPassportElementBankStatement(input);
				case InputPassportElementRentalAgreement.CONSTRUCTOR: return new InputPassportElementRentalAgreement(input);
				case InputPassportElementPassportRegistration.CONSTRUCTOR: return new InputPassportElementPassportRegistration(input);
				case InputPassportElementTemporaryRegistration.CONSTRUCTOR: return new InputPassportElementTemporaryRegistration(input);
				case InputPassportElementPhoneNumber.CONSTRUCTOR: return new InputPassportElementPhoneNumber(input);
				case InputPassportElementEmailAddress.CONSTRUCTOR: return new InputPassportElementEmailAddress(input);
				case InputPassportElementError.CONSTRUCTOR: return new InputPassportElementError(input);
				case InputPassportElementErrorSourceUnspecified.CONSTRUCTOR: return new InputPassportElementErrorSourceUnspecified(input);
				case InputPassportElementErrorSourceDataField.CONSTRUCTOR: return new InputPassportElementErrorSourceDataField(input);
				case InputPassportElementErrorSourceFrontSide.CONSTRUCTOR: return new InputPassportElementErrorSourceFrontSide(input);
				case InputPassportElementErrorSourceReverseSide.CONSTRUCTOR: return new InputPassportElementErrorSourceReverseSide(input);
				case InputPassportElementErrorSourceSelfie.CONSTRUCTOR: return new InputPassportElementErrorSourceSelfie(input);
				case InputPassportElementErrorSourceTranslationFile.CONSTRUCTOR: return new InputPassportElementErrorSourceTranslationFile(input);
				case InputPassportElementErrorSourceTranslationFiles.CONSTRUCTOR: return new InputPassportElementErrorSourceTranslationFiles(input);
				case InputPassportElementErrorSourceFile.CONSTRUCTOR: return new InputPassportElementErrorSourceFile(input);
				case InputPassportElementErrorSourceFiles.CONSTRUCTOR: return new InputPassportElementErrorSourceFiles(input);
				case InputPersonalDocument.CONSTRUCTOR: return new InputPersonalDocument(input);
				case InputSticker.CONSTRUCTOR: return new InputSticker(input);
				case InputThumbnail.CONSTRUCTOR: return new InputThumbnail(input);
				case InternalLinkTypeActiveSessions.CONSTRUCTOR: return new InternalLinkTypeActiveSessions(input);
				case InternalLinkTypeAttachmentMenuBot.CONSTRUCTOR: return new InternalLinkTypeAttachmentMenuBot(input);
				case InternalLinkTypeAuthenticationCode.CONSTRUCTOR: return new InternalLinkTypeAuthenticationCode(input);
				case InternalLinkTypeBackground.CONSTRUCTOR: return new InternalLinkTypeBackground(input);
				case InternalLinkTypeBotAddToChannel.CONSTRUCTOR: return new InternalLinkTypeBotAddToChannel(input);
				case InternalLinkTypeBotStart.CONSTRUCTOR: return new InternalLinkTypeBotStart(input);
				case InternalLinkTypeBotStartInGroup.CONSTRUCTOR: return new InternalLinkTypeBotStartInGroup(input);
				case InternalLinkTypeChangePhoneNumber.CONSTRUCTOR: return new InternalLinkTypeChangePhoneNumber(input);
				case InternalLinkTypeChatFolderInvite.CONSTRUCTOR: return new InternalLinkTypeChatFolderInvite(input);
				case InternalLinkTypeChatFolderSettings.CONSTRUCTOR: return new InternalLinkTypeChatFolderSettings(input);
				case InternalLinkTypeChatInvite.CONSTRUCTOR: return new InternalLinkTypeChatInvite(input);
				case InternalLinkTypeDefaultMessageAutoDeleteTimerSettings.CONSTRUCTOR: return new InternalLinkTypeDefaultMessageAutoDeleteTimerSettings(input);
				case InternalLinkTypeEditProfileSettings.CONSTRUCTOR: return new InternalLinkTypeEditProfileSettings(input);
				case InternalLinkTypeGame.CONSTRUCTOR: return new InternalLinkTypeGame(input);
				case InternalLinkTypeInstantView.CONSTRUCTOR: return new InternalLinkTypeInstantView(input);
				case InternalLinkTypeInvoice.CONSTRUCTOR: return new InternalLinkTypeInvoice(input);
				case InternalLinkTypeLanguagePack.CONSTRUCTOR: return new InternalLinkTypeLanguagePack(input);
				case InternalLinkTypeLanguageSettings.CONSTRUCTOR: return new InternalLinkTypeLanguageSettings(input);
				case InternalLinkTypeMessage.CONSTRUCTOR: return new InternalLinkTypeMessage(input);
				case InternalLinkTypeMessageDraft.CONSTRUCTOR: return new InternalLinkTypeMessageDraft(input);
				case InternalLinkTypePassportDataRequest.CONSTRUCTOR: return new InternalLinkTypePassportDataRequest(input);
				case InternalLinkTypePhoneNumberConfirmation.CONSTRUCTOR: return new InternalLinkTypePhoneNumberConfirmation(input);
				case InternalLinkTypePremiumFeatures.CONSTRUCTOR: return new InternalLinkTypePremiumFeatures(input);
				case InternalLinkTypePrivacyAndSecuritySettings.CONSTRUCTOR: return new InternalLinkTypePrivacyAndSecuritySettings(input);
				case InternalLinkTypeProxy.CONSTRUCTOR: return new InternalLinkTypeProxy(input);
				case InternalLinkTypePublicChat.CONSTRUCTOR: return new InternalLinkTypePublicChat(input);
				case InternalLinkTypeQrCodeAuthentication.CONSTRUCTOR: return new InternalLinkTypeQrCodeAuthentication(input);
				case InternalLinkTypeRestorePurchases.CONSTRUCTOR: return new InternalLinkTypeRestorePurchases(input);
				case InternalLinkTypeSettings.CONSTRUCTOR: return new InternalLinkTypeSettings(input);
				case InternalLinkTypeStickerSet.CONSTRUCTOR: return new InternalLinkTypeStickerSet(input);
				case InternalLinkTypeTheme.CONSTRUCTOR: return new InternalLinkTypeTheme(input);
				case InternalLinkTypeThemeSettings.CONSTRUCTOR: return new InternalLinkTypeThemeSettings(input);
				case InternalLinkTypeUnknownDeepLink.CONSTRUCTOR: return new InternalLinkTypeUnknownDeepLink(input);
				case InternalLinkTypeUnsupportedProxy.CONSTRUCTOR: return new InternalLinkTypeUnsupportedProxy(input);
				case InternalLinkTypeUserPhoneNumber.CONSTRUCTOR: return new InternalLinkTypeUserPhoneNumber(input);
				case InternalLinkTypeUserToken.CONSTRUCTOR: return new InternalLinkTypeUserToken(input);
				case InternalLinkTypeVideoChat.CONSTRUCTOR: return new InternalLinkTypeVideoChat(input);
				case InternalLinkTypeWebApp.CONSTRUCTOR: return new InternalLinkTypeWebApp(input);
				case Invoice.CONSTRUCTOR: return new Invoice(input);
				case JsonObjectMember.CONSTRUCTOR: return new JsonObjectMember(input);
				case JsonValueNull.CONSTRUCTOR: return new JsonValueNull(input);
				case JsonValueBoolean.CONSTRUCTOR: return new JsonValueBoolean(input);
				case JsonValueNumber.CONSTRUCTOR: return new JsonValueNumber(input);
				case JsonValueString.CONSTRUCTOR: return new JsonValueString(input);
				case JsonValueArray.CONSTRUCTOR: return new JsonValueArray(input);
				case JsonValueObject.CONSTRUCTOR: return new JsonValueObject(input);
				case KeyboardButton.CONSTRUCTOR: return new KeyboardButton(input);
				case KeyboardButtonTypeText.CONSTRUCTOR: return new KeyboardButtonTypeText(input);
				case KeyboardButtonTypeRequestPhoneNumber.CONSTRUCTOR: return new KeyboardButtonTypeRequestPhoneNumber(input);
				case KeyboardButtonTypeRequestLocation.CONSTRUCTOR: return new KeyboardButtonTypeRequestLocation(input);
				case KeyboardButtonTypeRequestPoll.CONSTRUCTOR: return new KeyboardButtonTypeRequestPoll(input);
				case KeyboardButtonTypeRequestUser.CONSTRUCTOR: return new KeyboardButtonTypeRequestUser(input);
				case KeyboardButtonTypeRequestChat.CONSTRUCTOR: return new KeyboardButtonTypeRequestChat(input);
				case KeyboardButtonTypeWebApp.CONSTRUCTOR: return new KeyboardButtonTypeWebApp(input);
				case LabeledPricePart.CONSTRUCTOR: return new LabeledPricePart(input);
				case LanguagePackInfo.CONSTRUCTOR: return new LanguagePackInfo(input);
				case LanguagePackString.CONSTRUCTOR: return new LanguagePackString(input);
				case LanguagePackStringValueOrdinary.CONSTRUCTOR: return new LanguagePackStringValueOrdinary(input);
				case LanguagePackStringValuePluralized.CONSTRUCTOR: return new LanguagePackStringValuePluralized(input);
				case LanguagePackStringValueDeleted.CONSTRUCTOR: return new LanguagePackStringValueDeleted(input);
				case LanguagePackStrings.CONSTRUCTOR: return new LanguagePackStrings(input);
				case LocalFile.CONSTRUCTOR: return new LocalFile(input);
				case LocalizationTargetInfo.CONSTRUCTOR: return new LocalizationTargetInfo(input);
				case Location.CONSTRUCTOR: return new Location(input);
				case LogStreamDefault.CONSTRUCTOR: return new LogStreamDefault(input);
				case LogStreamFile.CONSTRUCTOR: return new LogStreamFile(input);
				case LogStreamEmpty.CONSTRUCTOR: return new LogStreamEmpty(input);
				case LogTags.CONSTRUCTOR: return new LogTags(input);
				case LogVerbosityLevel.CONSTRUCTOR: return new LogVerbosityLevel(input);
				case LoginUrlInfoOpen.CONSTRUCTOR: return new LoginUrlInfoOpen(input);
				case LoginUrlInfoRequestConfirmation.CONSTRUCTOR: return new LoginUrlInfoRequestConfirmation(input);
				case MaskPointForehead.CONSTRUCTOR: return new MaskPointForehead(input);
				case MaskPointEyes.CONSTRUCTOR: return new MaskPointEyes(input);
				case MaskPointMouth.CONSTRUCTOR: return new MaskPointMouth(input);
				case MaskPointChin.CONSTRUCTOR: return new MaskPointChin(input);
				case MaskPosition.CONSTRUCTOR: return new MaskPosition(input);
				case MemoryStatistics.CONSTRUCTOR: return new MemoryStatistics(input);
				case Message.CONSTRUCTOR: return new Message(input);
				case MessageAutoDeleteTime.CONSTRUCTOR: return new MessageAutoDeleteTime(input);
				case MessageCalendar.CONSTRUCTOR: return new MessageCalendar(input);
				case MessageCalendarDay.CONSTRUCTOR: return new MessageCalendarDay(input);
				case MessageText.CONSTRUCTOR: return new MessageText(input);
				case MessageAnimation.CONSTRUCTOR: return new MessageAnimation(input);
				case MessageAudio.CONSTRUCTOR: return new MessageAudio(input);
				case MessageDocument.CONSTRUCTOR: return new MessageDocument(input);
				case MessagePhoto.CONSTRUCTOR: return new MessagePhoto(input);
				case MessageExpiredPhoto.CONSTRUCTOR: return new MessageExpiredPhoto(input);
				case MessageSticker.CONSTRUCTOR: return new MessageSticker(input);
				case MessageVideo.CONSTRUCTOR: return new MessageVideo(input);
				case MessageExpiredVideo.CONSTRUCTOR: return new MessageExpiredVideo(input);
				case MessageVideoNote.CONSTRUCTOR: return new MessageVideoNote(input);
				case MessageVoiceNote.CONSTRUCTOR: return new MessageVoiceNote(input);
				case MessageLocation.CONSTRUCTOR: return new MessageLocation(input);
				case MessageVenue.CONSTRUCTOR: return new MessageVenue(input);
				case MessageContact.CONSTRUCTOR: return new MessageContact(input);
				case MessageAnimatedEmoji.CONSTRUCTOR: return new MessageAnimatedEmoji(input);
				case MessageDice.CONSTRUCTOR: return new MessageDice(input);
				case MessageGame.CONSTRUCTOR: return new MessageGame(input);
				case MessagePoll.CONSTRUCTOR: return new MessagePoll(input);
				case MessageInvoice.CONSTRUCTOR: return new MessageInvoice(input);
				case MessageCall.CONSTRUCTOR: return new MessageCall(input);
				case MessageVideoChatScheduled.CONSTRUCTOR: return new MessageVideoChatScheduled(input);
				case MessageVideoChatStarted.CONSTRUCTOR: return new MessageVideoChatStarted(input);
				case MessageVideoChatEnded.CONSTRUCTOR: return new MessageVideoChatEnded(input);
				case MessageInviteVideoChatParticipants.CONSTRUCTOR: return new MessageInviteVideoChatParticipants(input);
				case MessageBasicGroupChatCreate.CONSTRUCTOR: return new MessageBasicGroupChatCreate(input);
				case MessageSupergroupChatCreate.CONSTRUCTOR: return new MessageSupergroupChatCreate(input);
				case MessageChatChangeTitle.CONSTRUCTOR: return new MessageChatChangeTitle(input);
				case MessageChatChangePhoto.CONSTRUCTOR: return new MessageChatChangePhoto(input);
				case MessageChatDeletePhoto.CONSTRUCTOR: return new MessageChatDeletePhoto(input);
				case MessageChatAddMembers.CONSTRUCTOR: return new MessageChatAddMembers(input);
				case MessageChatJoinByLink.CONSTRUCTOR: return new MessageChatJoinByLink(input);
				case MessageChatJoinByRequest.CONSTRUCTOR: return new MessageChatJoinByRequest(input);
				case MessageChatDeleteMember.CONSTRUCTOR: return new MessageChatDeleteMember(input);
				case MessageChatUpgradeTo.CONSTRUCTOR: return new MessageChatUpgradeTo(input);
				case MessageChatUpgradeFrom.CONSTRUCTOR: return new MessageChatUpgradeFrom(input);
				case MessagePinMessage.CONSTRUCTOR: return new MessagePinMessage(input);
				case MessageScreenshotTaken.CONSTRUCTOR: return new MessageScreenshotTaken(input);
				case MessageChatSetBackground.CONSTRUCTOR: return new MessageChatSetBackground(input);
				case MessageChatSetTheme.CONSTRUCTOR: return new MessageChatSetTheme(input);
				case MessageChatSetMessageAutoDeleteTime.CONSTRUCTOR: return new MessageChatSetMessageAutoDeleteTime(input);
				case MessageForumTopicCreated.CONSTRUCTOR: return new MessageForumTopicCreated(input);
				case MessageForumTopicEdited.CONSTRUCTOR: return new MessageForumTopicEdited(input);
				case MessageForumTopicIsClosedToggled.CONSTRUCTOR: return new MessageForumTopicIsClosedToggled(input);
				case MessageForumTopicIsHiddenToggled.CONSTRUCTOR: return new MessageForumTopicIsHiddenToggled(input);
				case MessageSuggestProfilePhoto.CONSTRUCTOR: return new MessageSuggestProfilePhoto(input);
				case MessageCustomServiceAction.CONSTRUCTOR: return new MessageCustomServiceAction(input);
				case MessageGameScore.CONSTRUCTOR: return new MessageGameScore(input);
				case MessagePaymentSuccessful.CONSTRUCTOR: return new MessagePaymentSuccessful(input);
				case MessagePaymentSuccessfulBot.CONSTRUCTOR: return new MessagePaymentSuccessfulBot(input);
				case MessageGiftedPremium.CONSTRUCTOR: return new MessageGiftedPremium(input);
				case MessageContactRegistered.CONSTRUCTOR: return new MessageContactRegistered(input);
				case MessageUserShared.CONSTRUCTOR: return new MessageUserShared(input);
				case MessageChatShared.CONSTRUCTOR: return new MessageChatShared(input);
				case MessageWebsiteConnected.CONSTRUCTOR: return new MessageWebsiteConnected(input);
				case MessageBotWriteAccessAllowed.CONSTRUCTOR: return new MessageBotWriteAccessAllowed(input);
				case MessageWebAppDataSent.CONSTRUCTOR: return new MessageWebAppDataSent(input);
				case MessageWebAppDataReceived.CONSTRUCTOR: return new MessageWebAppDataReceived(input);
				case MessagePassportDataSent.CONSTRUCTOR: return new MessagePassportDataSent(input);
				case MessagePassportDataReceived.CONSTRUCTOR: return new MessagePassportDataReceived(input);
				case MessageProximityAlertTriggered.CONSTRUCTOR: return new MessageProximityAlertTriggered(input);
				case MessageUnsupported.CONSTRUCTOR: return new MessageUnsupported(input);
				case MessageCopyOptions.CONSTRUCTOR: return new MessageCopyOptions(input);
				case MessageExtendedMediaPreview.CONSTRUCTOR: return new MessageExtendedMediaPreview(input);
				case MessageExtendedMediaPhoto.CONSTRUCTOR: return new MessageExtendedMediaPhoto(input);
				case MessageExtendedMediaVideo.CONSTRUCTOR: return new MessageExtendedMediaVideo(input);
				case MessageExtendedMediaUnsupported.CONSTRUCTOR: return new MessageExtendedMediaUnsupported(input);
				case MessageFileTypePrivate.CONSTRUCTOR: return new MessageFileTypePrivate(input);
				case MessageFileTypeGroup.CONSTRUCTOR: return new MessageFileTypeGroup(input);
				case MessageFileTypeUnknown.CONSTRUCTOR: return new MessageFileTypeUnknown(input);
				case MessageForwardInfo.CONSTRUCTOR: return new MessageForwardInfo(input);
				case MessageForwardOriginUser.CONSTRUCTOR: return new MessageForwardOriginUser(input);
				case MessageForwardOriginChat.CONSTRUCTOR: return new MessageForwardOriginChat(input);
				case MessageForwardOriginHiddenUser.CONSTRUCTOR: return new MessageForwardOriginHiddenUser(input);
				case MessageForwardOriginChannel.CONSTRUCTOR: return new MessageForwardOriginChannel(input);
				case MessageForwardOriginMessageImport.CONSTRUCTOR: return new MessageForwardOriginMessageImport(input);
				case MessageInteractionInfo.CONSTRUCTOR: return new MessageInteractionInfo(input);
				case MessageLink.CONSTRUCTOR: return new MessageLink(input);
				case MessageLinkInfo.CONSTRUCTOR: return new MessageLinkInfo(input);
				case MessagePosition.CONSTRUCTOR: return new MessagePosition(input);
				case MessagePositions.CONSTRUCTOR: return new MessagePositions(input);
				case MessageReaction.CONSTRUCTOR: return new MessageReaction(input);
				case MessageReplyInfo.CONSTRUCTOR: return new MessageReplyInfo(input);
				case MessageSchedulingStateSendAtDate.CONSTRUCTOR: return new MessageSchedulingStateSendAtDate(input);
				case MessageSchedulingStateSendWhenOnline.CONSTRUCTOR: return new MessageSchedulingStateSendWhenOnline(input);
				case MessageSendOptions.CONSTRUCTOR: return new MessageSendOptions(input);
				case MessageSenderUser.CONSTRUCTOR: return new MessageSenderUser(input);
				case MessageSenderChat.CONSTRUCTOR: return new MessageSenderChat(input);
				case MessageSenders.CONSTRUCTOR: return new MessageSenders(input);
				case MessageSendingStatePending.CONSTRUCTOR: return new MessageSendingStatePending(input);
				case MessageSendingStateFailed.CONSTRUCTOR: return new MessageSendingStateFailed(input);
				case MessageSourceChatHistory.CONSTRUCTOR: return new MessageSourceChatHistory(input);
				case MessageSourceMessageThreadHistory.CONSTRUCTOR: return new MessageSourceMessageThreadHistory(input);
				case MessageSourceForumTopicHistory.CONSTRUCTOR: return new MessageSourceForumTopicHistory(input);
				case MessageSourceHistoryPreview.CONSTRUCTOR: return new MessageSourceHistoryPreview(input);
				case MessageSourceChatList.CONSTRUCTOR: return new MessageSourceChatList(input);
				case MessageSourceSearch.CONSTRUCTOR: return new MessageSourceSearch(input);
				case MessageSourceChatEventLog.CONSTRUCTOR: return new MessageSourceChatEventLog(input);
				case MessageSourceNotification.CONSTRUCTOR: return new MessageSourceNotification(input);
				case MessageSourceOther.CONSTRUCTOR: return new MessageSourceOther(input);
				case MessageStatistics.CONSTRUCTOR: return new MessageStatistics(input);
				case MessageThreadInfo.CONSTRUCTOR: return new MessageThreadInfo(input);
				case MessageViewer.CONSTRUCTOR: return new MessageViewer(input);
				case MessageViewers.CONSTRUCTOR: return new MessageViewers(input);
				case Messages.CONSTRUCTOR: return new Messages(input);
				case Minithumbnail.CONSTRUCTOR: return new Minithumbnail(input);
				case NetworkStatistics.CONSTRUCTOR: return new NetworkStatistics(input);
				case NetworkStatisticsEntryFile.CONSTRUCTOR: return new NetworkStatisticsEntryFile(input);
				case NetworkStatisticsEntryCall.CONSTRUCTOR: return new NetworkStatisticsEntryCall(input);
				case NetworkTypeNone.CONSTRUCTOR: return new NetworkTypeNone(input);
				case NetworkTypeMobile.CONSTRUCTOR: return new NetworkTypeMobile(input);
				case NetworkTypeMobileRoaming.CONSTRUCTOR: return new NetworkTypeMobileRoaming(input);
				case NetworkTypeWiFi.CONSTRUCTOR: return new NetworkTypeWiFi(input);
				case NetworkTypeOther.CONSTRUCTOR: return new NetworkTypeOther(input);
				case Notification.CONSTRUCTOR: return new Notification(input);
				case NotificationGroup.CONSTRUCTOR: return new NotificationGroup(input);
				case NotificationGroupTypeMessages.CONSTRUCTOR: return new NotificationGroupTypeMessages(input);
				case NotificationGroupTypeMentions.CONSTRUCTOR: return new NotificationGroupTypeMentions(input);
				case NotificationGroupTypeSecretChat.CONSTRUCTOR: return new NotificationGroupTypeSecretChat(input);
				case NotificationGroupTypeCalls.CONSTRUCTOR: return new NotificationGroupTypeCalls(input);
				case NotificationSettingsScopePrivateChats.CONSTRUCTOR: return new NotificationSettingsScopePrivateChats(input);
				case NotificationSettingsScopeGroupChats.CONSTRUCTOR: return new NotificationSettingsScopeGroupChats(input);
				case NotificationSettingsScopeChannelChats.CONSTRUCTOR: return new NotificationSettingsScopeChannelChats(input);
				case NotificationSound.CONSTRUCTOR: return new NotificationSound(input);
				case NotificationSounds.CONSTRUCTOR: return new NotificationSounds(input);
				case NotificationTypeNewMessage.CONSTRUCTOR: return new NotificationTypeNewMessage(input);
				case NotificationTypeNewSecretChat.CONSTRUCTOR: return new NotificationTypeNewSecretChat(input);
				case NotificationTypeNewCall.CONSTRUCTOR: return new NotificationTypeNewCall(input);
				case NotificationTypeNewPushMessage.CONSTRUCTOR: return new NotificationTypeNewPushMessage(input);
				case Ok.CONSTRUCTOR: return new Ok(input);
				case OptionValueBoolean.CONSTRUCTOR: return new OptionValueBoolean(input);
				case OptionValueEmpty.CONSTRUCTOR: return new OptionValueEmpty(input);
				case OptionValueInteger.CONSTRUCTOR: return new OptionValueInteger(input);
				case OptionValueString.CONSTRUCTOR: return new OptionValueString(input);
				case OrderInfo.CONSTRUCTOR: return new OrderInfo(input);
				case PageBlockTitle.CONSTRUCTOR: return new PageBlockTitle(input);
				case PageBlockSubtitle.CONSTRUCTOR: return new PageBlockSubtitle(input);
				case PageBlockAuthorDate.CONSTRUCTOR: return new PageBlockAuthorDate(input);
				case PageBlockHeader.CONSTRUCTOR: return new PageBlockHeader(input);
				case PageBlockSubheader.CONSTRUCTOR: return new PageBlockSubheader(input);
				case PageBlockKicker.CONSTRUCTOR: return new PageBlockKicker(input);
				case PageBlockParagraph.CONSTRUCTOR: return new PageBlockParagraph(input);
				case PageBlockPreformatted.CONSTRUCTOR: return new PageBlockPreformatted(input);
				case PageBlockFooter.CONSTRUCTOR: return new PageBlockFooter(input);
				case PageBlockDivider.CONSTRUCTOR: return new PageBlockDivider(input);
				case PageBlockAnchor.CONSTRUCTOR: return new PageBlockAnchor(input);
				case PageBlockList.CONSTRUCTOR: return new PageBlockList(input);
				case PageBlockBlockQuote.CONSTRUCTOR: return new PageBlockBlockQuote(input);
				case PageBlockPullQuote.CONSTRUCTOR: return new PageBlockPullQuote(input);
				case PageBlockAnimation.CONSTRUCTOR: return new PageBlockAnimation(input);
				case PageBlockAudio.CONSTRUCTOR: return new PageBlockAudio(input);
				case PageBlockPhoto.CONSTRUCTOR: return new PageBlockPhoto(input);
				case PageBlockVideo.CONSTRUCTOR: return new PageBlockVideo(input);
				case PageBlockVoiceNote.CONSTRUCTOR: return new PageBlockVoiceNote(input);
				case PageBlockCover.CONSTRUCTOR: return new PageBlockCover(input);
				case PageBlockEmbedded.CONSTRUCTOR: return new PageBlockEmbedded(input);
				case PageBlockEmbeddedPost.CONSTRUCTOR: return new PageBlockEmbeddedPost(input);
				case PageBlockCollage.CONSTRUCTOR: return new PageBlockCollage(input);
				case PageBlockSlideshow.CONSTRUCTOR: return new PageBlockSlideshow(input);
				case PageBlockChatLink.CONSTRUCTOR: return new PageBlockChatLink(input);
				case PageBlockTable.CONSTRUCTOR: return new PageBlockTable(input);
				case PageBlockDetails.CONSTRUCTOR: return new PageBlockDetails(input);
				case PageBlockRelatedArticles.CONSTRUCTOR: return new PageBlockRelatedArticles(input);
				case PageBlockMap.CONSTRUCTOR: return new PageBlockMap(input);
				case PageBlockCaption.CONSTRUCTOR: return new PageBlockCaption(input);
				case PageBlockHorizontalAlignmentLeft.CONSTRUCTOR: return new PageBlockHorizontalAlignmentLeft(input);
				case PageBlockHorizontalAlignmentCenter.CONSTRUCTOR: return new PageBlockHorizontalAlignmentCenter(input);
				case PageBlockHorizontalAlignmentRight.CONSTRUCTOR: return new PageBlockHorizontalAlignmentRight(input);
				case PageBlockListItem.CONSTRUCTOR: return new PageBlockListItem(input);
				case PageBlockRelatedArticle.CONSTRUCTOR: return new PageBlockRelatedArticle(input);
				case PageBlockTableCell.CONSTRUCTOR: return new PageBlockTableCell(input);
				case PageBlockVerticalAlignmentTop.CONSTRUCTOR: return new PageBlockVerticalAlignmentTop(input);
				case PageBlockVerticalAlignmentMiddle.CONSTRUCTOR: return new PageBlockVerticalAlignmentMiddle(input);
				case PageBlockVerticalAlignmentBottom.CONSTRUCTOR: return new PageBlockVerticalAlignmentBottom(input);
				case PassportAuthorizationForm.CONSTRUCTOR: return new PassportAuthorizationForm(input);
				case PassportElementPersonalDetails.CONSTRUCTOR: return new PassportElementPersonalDetails(input);
				case PassportElementPassport.CONSTRUCTOR: return new PassportElementPassport(input);
				case PassportElementDriverLicense.CONSTRUCTOR: return new PassportElementDriverLicense(input);
				case PassportElementIdentityCard.CONSTRUCTOR: return new PassportElementIdentityCard(input);
				case PassportElementInternalPassport.CONSTRUCTOR: return new PassportElementInternalPassport(input);
				case PassportElementAddress.CONSTRUCTOR: return new PassportElementAddress(input);
				case PassportElementUtilityBill.CONSTRUCTOR: return new PassportElementUtilityBill(input);
				case PassportElementBankStatement.CONSTRUCTOR: return new PassportElementBankStatement(input);
				case PassportElementRentalAgreement.CONSTRUCTOR: return new PassportElementRentalAgreement(input);
				case PassportElementPassportRegistration.CONSTRUCTOR: return new PassportElementPassportRegistration(input);
				case PassportElementTemporaryRegistration.CONSTRUCTOR: return new PassportElementTemporaryRegistration(input);
				case PassportElementPhoneNumber.CONSTRUCTOR: return new PassportElementPhoneNumber(input);
				case PassportElementEmailAddress.CONSTRUCTOR: return new PassportElementEmailAddress(input);
				case PassportElementError.CONSTRUCTOR: return new PassportElementError(input);
				case PassportElementErrorSourceUnspecified.CONSTRUCTOR: return new PassportElementErrorSourceUnspecified(input);
				case PassportElementErrorSourceDataField.CONSTRUCTOR: return new PassportElementErrorSourceDataField(input);
				case PassportElementErrorSourceFrontSide.CONSTRUCTOR: return new PassportElementErrorSourceFrontSide(input);
				case PassportElementErrorSourceReverseSide.CONSTRUCTOR: return new PassportElementErrorSourceReverseSide(input);
				case PassportElementErrorSourceSelfie.CONSTRUCTOR: return new PassportElementErrorSourceSelfie(input);
				case PassportElementErrorSourceTranslationFile.CONSTRUCTOR: return new PassportElementErrorSourceTranslationFile(input);
				case PassportElementErrorSourceTranslationFiles.CONSTRUCTOR: return new PassportElementErrorSourceTranslationFiles(input);
				case PassportElementErrorSourceFile.CONSTRUCTOR: return new PassportElementErrorSourceFile(input);
				case PassportElementErrorSourceFiles.CONSTRUCTOR: return new PassportElementErrorSourceFiles(input);
				case PassportElementTypePersonalDetails.CONSTRUCTOR: return new PassportElementTypePersonalDetails(input);
				case PassportElementTypePassport.CONSTRUCTOR: return new PassportElementTypePassport(input);
				case PassportElementTypeDriverLicense.CONSTRUCTOR: return new PassportElementTypeDriverLicense(input);
				case PassportElementTypeIdentityCard.CONSTRUCTOR: return new PassportElementTypeIdentityCard(input);
				case PassportElementTypeInternalPassport.CONSTRUCTOR: return new PassportElementTypeInternalPassport(input);
				case PassportElementTypeAddress.CONSTRUCTOR: return new PassportElementTypeAddress(input);
				case PassportElementTypeUtilityBill.CONSTRUCTOR: return new PassportElementTypeUtilityBill(input);
				case PassportElementTypeBankStatement.CONSTRUCTOR: return new PassportElementTypeBankStatement(input);
				case PassportElementTypeRentalAgreement.CONSTRUCTOR: return new PassportElementTypeRentalAgreement(input);
				case PassportElementTypePassportRegistration.CONSTRUCTOR: return new PassportElementTypePassportRegistration(input);
				case PassportElementTypeTemporaryRegistration.CONSTRUCTOR: return new PassportElementTypeTemporaryRegistration(input);
				case PassportElementTypePhoneNumber.CONSTRUCTOR: return new PassportElementTypePhoneNumber(input);
				case PassportElementTypeEmailAddress.CONSTRUCTOR: return new PassportElementTypeEmailAddress(input);
				case PassportElements.CONSTRUCTOR: return new PassportElements(input);
				case PassportElementsWithErrors.CONSTRUCTOR: return new PassportElementsWithErrors(input);
				case PassportRequiredElement.CONSTRUCTOR: return new PassportRequiredElement(input);
				case PassportSuitableElement.CONSTRUCTOR: return new PassportSuitableElement(input);
				case PasswordState.CONSTRUCTOR: return new PasswordState(input);
				case PaymentForm.CONSTRUCTOR: return new PaymentForm(input);
				case PaymentOption.CONSTRUCTOR: return new PaymentOption(input);
				case PaymentProviderSmartGlocal.CONSTRUCTOR: return new PaymentProviderSmartGlocal(input);
				case PaymentProviderStripe.CONSTRUCTOR: return new PaymentProviderStripe(input);
				case PaymentProviderOther.CONSTRUCTOR: return new PaymentProviderOther(input);
				case PaymentReceipt.CONSTRUCTOR: return new PaymentReceipt(input);
				case PaymentResult.CONSTRUCTOR: return new PaymentResult(input);
				case PersonalDetails.CONSTRUCTOR: return new PersonalDetails(input);
				case PersonalDocument.CONSTRUCTOR: return new PersonalDocument(input);
				case PhoneNumberAuthenticationSettings.CONSTRUCTOR: return new PhoneNumberAuthenticationSettings(input);
				case PhoneNumberInfo.CONSTRUCTOR: return new PhoneNumberInfo(input);
				case Photo.CONSTRUCTOR: return new Photo(input);
				case PhotoSize.CONSTRUCTOR: return new PhotoSize(input);
				case Point.CONSTRUCTOR: return new Point(input);
				case Poll.CONSTRUCTOR: return new Poll(input);
				case PollOption.CONSTRUCTOR: return new PollOption(input);
				case PollTypeRegular.CONSTRUCTOR: return new PollTypeRegular(input);
				case PollTypeQuiz.CONSTRUCTOR: return new PollTypeQuiz(input);
				case PremiumFeatureIncreasedLimits.CONSTRUCTOR: return new PremiumFeatureIncreasedLimits(input);
				case PremiumFeatureIncreasedUploadFileSize.CONSTRUCTOR: return new PremiumFeatureIncreasedUploadFileSize(input);
				case PremiumFeatureImprovedDownloadSpeed.CONSTRUCTOR: return new PremiumFeatureImprovedDownloadSpeed(input);
				case PremiumFeatureVoiceRecognition.CONSTRUCTOR: return new PremiumFeatureVoiceRecognition(input);
				case PremiumFeatureDisabledAds.CONSTRUCTOR: return new PremiumFeatureDisabledAds(input);
				case PremiumFeatureUniqueReactions.CONSTRUCTOR: return new PremiumFeatureUniqueReactions(input);
				case PremiumFeatureUniqueStickers.CONSTRUCTOR: return new PremiumFeatureUniqueStickers(input);
				case PremiumFeatureCustomEmoji.CONSTRUCTOR: return new PremiumFeatureCustomEmoji(input);
				case PremiumFeatureAdvancedChatManagement.CONSTRUCTOR: return new PremiumFeatureAdvancedChatManagement(input);
				case PremiumFeatureProfileBadge.CONSTRUCTOR: return new PremiumFeatureProfileBadge(input);
				case PremiumFeatureEmojiStatus.CONSTRUCTOR: return new PremiumFeatureEmojiStatus(input);
				case PremiumFeatureAnimatedProfilePhoto.CONSTRUCTOR: return new PremiumFeatureAnimatedProfilePhoto(input);
				case PremiumFeatureForumTopicIcon.CONSTRUCTOR: return new PremiumFeatureForumTopicIcon(input);
				case PremiumFeatureAppIcons.CONSTRUCTOR: return new PremiumFeatureAppIcons(input);
				case PremiumFeatureRealTimeChatTranslation.CONSTRUCTOR: return new PremiumFeatureRealTimeChatTranslation(input);
				case PremiumFeaturePromotionAnimation.CONSTRUCTOR: return new PremiumFeaturePromotionAnimation(input);
				case PremiumFeatures.CONSTRUCTOR: return new PremiumFeatures(input);
				case PremiumLimit.CONSTRUCTOR: return new PremiumLimit(input);
				case PremiumLimitTypeSupergroupCount.CONSTRUCTOR: return new PremiumLimitTypeSupergroupCount(input);
				case PremiumLimitTypePinnedChatCount.CONSTRUCTOR: return new PremiumLimitTypePinnedChatCount(input);
				case PremiumLimitTypeCreatedPublicChatCount.CONSTRUCTOR: return new PremiumLimitTypeCreatedPublicChatCount(input);
				case PremiumLimitTypeSavedAnimationCount.CONSTRUCTOR: return new PremiumLimitTypeSavedAnimationCount(input);
				case PremiumLimitTypeFavoriteStickerCount.CONSTRUCTOR: return new PremiumLimitTypeFavoriteStickerCount(input);
				case PremiumLimitTypeChatFolderCount.CONSTRUCTOR: return new PremiumLimitTypeChatFolderCount(input);
				case PremiumLimitTypeChatFolderChosenChatCount.CONSTRUCTOR: return new PremiumLimitTypeChatFolderChosenChatCount(input);
				case PremiumLimitTypePinnedArchivedChatCount.CONSTRUCTOR: return new PremiumLimitTypePinnedArchivedChatCount(input);
				case PremiumLimitTypeCaptionLength.CONSTRUCTOR: return new PremiumLimitTypeCaptionLength(input);
				case PremiumLimitTypeBioLength.CONSTRUCTOR: return new PremiumLimitTypeBioLength(input);
				case PremiumLimitTypeChatFolderInviteLinkCount.CONSTRUCTOR: return new PremiumLimitTypeChatFolderInviteLinkCount(input);
				case PremiumLimitTypeShareableChatFolderCount.CONSTRUCTOR: return new PremiumLimitTypeShareableChatFolderCount(input);
				case PremiumPaymentOption.CONSTRUCTOR: return new PremiumPaymentOption(input);
				case PremiumSourceLimitExceeded.CONSTRUCTOR: return new PremiumSourceLimitExceeded(input);
				case PremiumSourceFeature.CONSTRUCTOR: return new PremiumSourceFeature(input);
				case PremiumSourceLink.CONSTRUCTOR: return new PremiumSourceLink(input);
				case PremiumSourceSettings.CONSTRUCTOR: return new PremiumSourceSettings(input);
				case PremiumState.CONSTRUCTOR: return new PremiumState(input);
				case PremiumStatePaymentOption.CONSTRUCTOR: return new PremiumStatePaymentOption(input);
				case ProfilePhoto.CONSTRUCTOR: return new ProfilePhoto(input);
				case Proxies.CONSTRUCTOR: return new Proxies(input);
				case Proxy.CONSTRUCTOR: return new Proxy(input);
				case ProxyTypeSocks5.CONSTRUCTOR: return new ProxyTypeSocks5(input);
				case ProxyTypeHttp.CONSTRUCTOR: return new ProxyTypeHttp(input);
				case ProxyTypeMtproto.CONSTRUCTOR: return new ProxyTypeMtproto(input);
				case PublicChatTypeHasUsername.CONSTRUCTOR: return new PublicChatTypeHasUsername(input);
				case PublicChatTypeIsLocationBased.CONSTRUCTOR: return new PublicChatTypeIsLocationBased(input);
				case PushMessageContentHidden.CONSTRUCTOR: return new PushMessageContentHidden(input);
				case PushMessageContentAnimation.CONSTRUCTOR: return new PushMessageContentAnimation(input);
				case PushMessageContentAudio.CONSTRUCTOR: return new PushMessageContentAudio(input);
				case PushMessageContentContact.CONSTRUCTOR: return new PushMessageContentContact(input);
				case PushMessageContentContactRegistered.CONSTRUCTOR: return new PushMessageContentContactRegistered(input);
				case PushMessageContentDocument.CONSTRUCTOR: return new PushMessageContentDocument(input);
				case PushMessageContentGame.CONSTRUCTOR: return new PushMessageContentGame(input);
				case PushMessageContentGameScore.CONSTRUCTOR: return new PushMessageContentGameScore(input);
				case PushMessageContentInvoice.CONSTRUCTOR: return new PushMessageContentInvoice(input);
				case PushMessageContentLocation.CONSTRUCTOR: return new PushMessageContentLocation(input);
				case PushMessageContentPhoto.CONSTRUCTOR: return new PushMessageContentPhoto(input);
				case PushMessageContentPoll.CONSTRUCTOR: return new PushMessageContentPoll(input);
				case PushMessageContentScreenshotTaken.CONSTRUCTOR: return new PushMessageContentScreenshotTaken(input);
				case PushMessageContentSticker.CONSTRUCTOR: return new PushMessageContentSticker(input);
				case PushMessageContentText.CONSTRUCTOR: return new PushMessageContentText(input);
				case PushMessageContentVideo.CONSTRUCTOR: return new PushMessageContentVideo(input);
				case PushMessageContentVideoNote.CONSTRUCTOR: return new PushMessageContentVideoNote(input);
				case PushMessageContentVoiceNote.CONSTRUCTOR: return new PushMessageContentVoiceNote(input);
				case PushMessageContentBasicGroupChatCreate.CONSTRUCTOR: return new PushMessageContentBasicGroupChatCreate(input);
				case PushMessageContentChatAddMembers.CONSTRUCTOR: return new PushMessageContentChatAddMembers(input);
				case PushMessageContentChatChangePhoto.CONSTRUCTOR: return new PushMessageContentChatChangePhoto(input);
				case PushMessageContentChatChangeTitle.CONSTRUCTOR: return new PushMessageContentChatChangeTitle(input);
				case PushMessageContentChatSetBackground.CONSTRUCTOR: return new PushMessageContentChatSetBackground(input);
				case PushMessageContentChatSetTheme.CONSTRUCTOR: return new PushMessageContentChatSetTheme(input);
				case PushMessageContentChatDeleteMember.CONSTRUCTOR: return new PushMessageContentChatDeleteMember(input);
				case PushMessageContentChatJoinByLink.CONSTRUCTOR: return new PushMessageContentChatJoinByLink(input);
				case PushMessageContentChatJoinByRequest.CONSTRUCTOR: return new PushMessageContentChatJoinByRequest(input);
				case PushMessageContentRecurringPayment.CONSTRUCTOR: return new PushMessageContentRecurringPayment(input);
				case PushMessageContentSuggestProfilePhoto.CONSTRUCTOR: return new PushMessageContentSuggestProfilePhoto(input);
				case PushMessageContentMessageForwards.CONSTRUCTOR: return new PushMessageContentMessageForwards(input);
				case PushMessageContentMediaAlbum.CONSTRUCTOR: return new PushMessageContentMediaAlbum(input);
				case PushReceiverId.CONSTRUCTOR: return new PushReceiverId(input);
				case ReactionTypeEmoji.CONSTRUCTOR: return new ReactionTypeEmoji(input);
				case ReactionTypeCustomEmoji.CONSTRUCTOR: return new ReactionTypeCustomEmoji(input);
				case RecommendedChatFolder.CONSTRUCTOR: return new RecommendedChatFolder(input);
				case RecommendedChatFolders.CONSTRUCTOR: return new RecommendedChatFolders(input);
				case RecoveryEmailAddress.CONSTRUCTOR: return new RecoveryEmailAddress(input);
				case RemoteFile.CONSTRUCTOR: return new RemoteFile(input);
				case ReplyMarkupRemoveKeyboard.CONSTRUCTOR: return new ReplyMarkupRemoveKeyboard(input);
				case ReplyMarkupForceReply.CONSTRUCTOR: return new ReplyMarkupForceReply(input);
				case ReplyMarkupShowKeyboard.CONSTRUCTOR: return new ReplyMarkupShowKeyboard(input);
				case ReplyMarkupInlineKeyboard.CONSTRUCTOR: return new ReplyMarkupInlineKeyboard(input);
				case ResetPasswordResultOk.CONSTRUCTOR: return new ResetPasswordResultOk(input);
				case ResetPasswordResultPending.CONSTRUCTOR: return new ResetPasswordResultPending(input);
				case ResetPasswordResultDeclined.CONSTRUCTOR: return new ResetPasswordResultDeclined(input);
				case RichTextPlain.CONSTRUCTOR: return new RichTextPlain(input);
				case RichTextBold.CONSTRUCTOR: return new RichTextBold(input);
				case RichTextItalic.CONSTRUCTOR: return new RichTextItalic(input);
				case RichTextUnderline.CONSTRUCTOR: return new RichTextUnderline(input);
				case RichTextStrikethrough.CONSTRUCTOR: return new RichTextStrikethrough(input);
				case RichTextFixed.CONSTRUCTOR: return new RichTextFixed(input);
				case RichTextUrl.CONSTRUCTOR: return new RichTextUrl(input);
				case RichTextEmailAddress.CONSTRUCTOR: return new RichTextEmailAddress(input);
				case RichTextSubscript.CONSTRUCTOR: return new RichTextSubscript(input);
				case RichTextSuperscript.CONSTRUCTOR: return new RichTextSuperscript(input);
				case RichTextMarked.CONSTRUCTOR: return new RichTextMarked(input);
				case RichTextPhoneNumber.CONSTRUCTOR: return new RichTextPhoneNumber(input);
				case RichTextIcon.CONSTRUCTOR: return new RichTextIcon(input);
				case RichTextReference.CONSTRUCTOR: return new RichTextReference(input);
				case RichTextAnchor.CONSTRUCTOR: return new RichTextAnchor(input);
				case RichTextAnchorLink.CONSTRUCTOR: return new RichTextAnchorLink(input);
				case RichTexts.CONSTRUCTOR: return new RichTexts(input);
				case RtmpUrl.CONSTRUCTOR: return new RtmpUrl(input);
				case SavedCredentials.CONSTRUCTOR: return new SavedCredentials(input);
				case ScopeAutosaveSettings.CONSTRUCTOR: return new ScopeAutosaveSettings(input);
				case ScopeNotificationSettings.CONSTRUCTOR: return new ScopeNotificationSettings(input);
				case SearchMessagesFilterEmpty.CONSTRUCTOR: return new SearchMessagesFilterEmpty(input);
				case SearchMessagesFilterAnimation.CONSTRUCTOR: return new SearchMessagesFilterAnimation(input);
				case SearchMessagesFilterAudio.CONSTRUCTOR: return new SearchMessagesFilterAudio(input);
				case SearchMessagesFilterDocument.CONSTRUCTOR: return new SearchMessagesFilterDocument(input);
				case SearchMessagesFilterPhoto.CONSTRUCTOR: return new SearchMessagesFilterPhoto(input);
				case SearchMessagesFilterVideo.CONSTRUCTOR: return new SearchMessagesFilterVideo(input);
				case SearchMessagesFilterVoiceNote.CONSTRUCTOR: return new SearchMessagesFilterVoiceNote(input);
				case SearchMessagesFilterPhotoAndVideo.CONSTRUCTOR: return new SearchMessagesFilterPhotoAndVideo(input);
				case SearchMessagesFilterUrl.CONSTRUCTOR: return new SearchMessagesFilterUrl(input);
				case SearchMessagesFilterChatPhoto.CONSTRUCTOR: return new SearchMessagesFilterChatPhoto(input);
				case SearchMessagesFilterVideoNote.CONSTRUCTOR: return new SearchMessagesFilterVideoNote(input);
				case SearchMessagesFilterVoiceAndVideoNote.CONSTRUCTOR: return new SearchMessagesFilterVoiceAndVideoNote(input);
				case SearchMessagesFilterMention.CONSTRUCTOR: return new SearchMessagesFilterMention(input);
				case SearchMessagesFilterUnreadMention.CONSTRUCTOR: return new SearchMessagesFilterUnreadMention(input);
				case SearchMessagesFilterUnreadReaction.CONSTRUCTOR: return new SearchMessagesFilterUnreadReaction(input);
				case SearchMessagesFilterFailedToSend.CONSTRUCTOR: return new SearchMessagesFilterFailedToSend(input);
				case SearchMessagesFilterPinned.CONSTRUCTOR: return new SearchMessagesFilterPinned(input);
				case Seconds.CONSTRUCTOR: return new Seconds(input);
				case SecretChat.CONSTRUCTOR: return new SecretChat(input);
				case SecretChatStatePending.CONSTRUCTOR: return new SecretChatStatePending(input);
				case SecretChatStateReady.CONSTRUCTOR: return new SecretChatStateReady(input);
				case SecretChatStateClosed.CONSTRUCTOR: return new SecretChatStateClosed(input);
				case SentWebAppMessage.CONSTRUCTOR: return new SentWebAppMessage(input);
				case Session.CONSTRUCTOR: return new Session(input);
				case SessionTypeAndroid.CONSTRUCTOR: return new SessionTypeAndroid(input);
				case SessionTypeApple.CONSTRUCTOR: return new SessionTypeApple(input);
				case SessionTypeBrave.CONSTRUCTOR: return new SessionTypeBrave(input);
				case SessionTypeChrome.CONSTRUCTOR: return new SessionTypeChrome(input);
				case SessionTypeEdge.CONSTRUCTOR: return new SessionTypeEdge(input);
				case SessionTypeFirefox.CONSTRUCTOR: return new SessionTypeFirefox(input);
				case SessionTypeIpad.CONSTRUCTOR: return new SessionTypeIpad(input);
				case SessionTypeIphone.CONSTRUCTOR: return new SessionTypeIphone(input);
				case SessionTypeLinux.CONSTRUCTOR: return new SessionTypeLinux(input);
				case SessionTypeMac.CONSTRUCTOR: return new SessionTypeMac(input);
				case SessionTypeOpera.CONSTRUCTOR: return new SessionTypeOpera(input);
				case SessionTypeSafari.CONSTRUCTOR: return new SessionTypeSafari(input);
				case SessionTypeUbuntu.CONSTRUCTOR: return new SessionTypeUbuntu(input);
				case SessionTypeUnknown.CONSTRUCTOR: return new SessionTypeUnknown(input);
				case SessionTypeVivaldi.CONSTRUCTOR: return new SessionTypeVivaldi(input);
				case SessionTypeWindows.CONSTRUCTOR: return new SessionTypeWindows(input);
				case SessionTypeXbox.CONSTRUCTOR: return new SessionTypeXbox(input);
				case Sessions.CONSTRUCTOR: return new Sessions(input);
				case ShippingOption.CONSTRUCTOR: return new ShippingOption(input);
				case SpeechRecognitionResultPending.CONSTRUCTOR: return new SpeechRecognitionResultPending(input);
				case SpeechRecognitionResultText.CONSTRUCTOR: return new SpeechRecognitionResultText(input);
				case SpeechRecognitionResultError.CONSTRUCTOR: return new SpeechRecognitionResultError(input);
				case SponsoredMessage.CONSTRUCTOR: return new SponsoredMessage(input);
				case SponsoredMessages.CONSTRUCTOR: return new SponsoredMessages(input);
				case StatisticalGraphData.CONSTRUCTOR: return new StatisticalGraphData(input);
				case StatisticalGraphAsync.CONSTRUCTOR: return new StatisticalGraphAsync(input);
				case StatisticalGraphError.CONSTRUCTOR: return new StatisticalGraphError(input);
				case StatisticalValue.CONSTRUCTOR: return new StatisticalValue(input);
				case Sticker.CONSTRUCTOR: return new Sticker(input);
				case StickerFormatWebp.CONSTRUCTOR: return new StickerFormatWebp(input);
				case StickerFormatTgs.CONSTRUCTOR: return new StickerFormatTgs(input);
				case StickerFormatWebm.CONSTRUCTOR: return new StickerFormatWebm(input);
				case StickerFullTypeRegular.CONSTRUCTOR: return new StickerFullTypeRegular(input);
				case StickerFullTypeMask.CONSTRUCTOR: return new StickerFullTypeMask(input);
				case StickerFullTypeCustomEmoji.CONSTRUCTOR: return new StickerFullTypeCustomEmoji(input);
				case StickerSet.CONSTRUCTOR: return new StickerSet(input);
				case StickerSetInfo.CONSTRUCTOR: return new StickerSetInfo(input);
				case StickerSets.CONSTRUCTOR: return new StickerSets(input);
				case StickerTypeRegular.CONSTRUCTOR: return new StickerTypeRegular(input);
				case StickerTypeMask.CONSTRUCTOR: return new StickerTypeMask(input);
				case StickerTypeCustomEmoji.CONSTRUCTOR: return new StickerTypeCustomEmoji(input);
				case Stickers.CONSTRUCTOR: return new Stickers(input);
				case StorageStatistics.CONSTRUCTOR: return new StorageStatistics(input);
				case StorageStatisticsByChat.CONSTRUCTOR: return new StorageStatisticsByChat(input);
				case StorageStatisticsByFileType.CONSTRUCTOR: return new StorageStatisticsByFileType(input);
				case StorageStatisticsFast.CONSTRUCTOR: return new StorageStatisticsFast(input);
				case StorePaymentPurposePremiumSubscription.CONSTRUCTOR: return new StorePaymentPurposePremiumSubscription(input);
				case StorePaymentPurposeGiftedPremium.CONSTRUCTOR: return new StorePaymentPurposeGiftedPremium(input);
				case SuggestedActionEnableArchiveAndMuteNewChats.CONSTRUCTOR: return new SuggestedActionEnableArchiveAndMuteNewChats(input);
				case SuggestedActionCheckPassword.CONSTRUCTOR: return new SuggestedActionCheckPassword(input);
				case SuggestedActionCheckPhoneNumber.CONSTRUCTOR: return new SuggestedActionCheckPhoneNumber(input);
				case SuggestedActionViewChecksHint.CONSTRUCTOR: return new SuggestedActionViewChecksHint(input);
				case SuggestedActionConvertToBroadcastGroup.CONSTRUCTOR: return new SuggestedActionConvertToBroadcastGroup(input);
				case SuggestedActionSetPassword.CONSTRUCTOR: return new SuggestedActionSetPassword(input);
				case SuggestedActionUpgradePremium.CONSTRUCTOR: return new SuggestedActionUpgradePremium(input);
				case SuggestedActionSubscribeToAnnualPremium.CONSTRUCTOR: return new SuggestedActionSubscribeToAnnualPremium(input);
				case Supergroup.CONSTRUCTOR: return new Supergroup(input);
				case SupergroupFullInfo.CONSTRUCTOR: return new SupergroupFullInfo(input);
				case SupergroupMembersFilterRecent.CONSTRUCTOR: return new SupergroupMembersFilterRecent(input);
				case SupergroupMembersFilterContacts.CONSTRUCTOR: return new SupergroupMembersFilterContacts(input);
				case SupergroupMembersFilterAdministrators.CONSTRUCTOR: return new SupergroupMembersFilterAdministrators(input);
				case SupergroupMembersFilterSearch.CONSTRUCTOR: return new SupergroupMembersFilterSearch(input);
				case SupergroupMembersFilterRestricted.CONSTRUCTOR: return new SupergroupMembersFilterRestricted(input);
				case SupergroupMembersFilterBanned.CONSTRUCTOR: return new SupergroupMembersFilterBanned(input);
				case SupergroupMembersFilterMention.CONSTRUCTOR: return new SupergroupMembersFilterMention(input);
				case SupergroupMembersFilterBots.CONSTRUCTOR: return new SupergroupMembersFilterBots(input);
				case TMeUrl.CONSTRUCTOR: return new TMeUrl(input);
				case TMeUrlTypeUser.CONSTRUCTOR: return new TMeUrlTypeUser(input);
				case TMeUrlTypeSupergroup.CONSTRUCTOR: return new TMeUrlTypeSupergroup(input);
				case TMeUrlTypeChatInvite.CONSTRUCTOR: return new TMeUrlTypeChatInvite(input);
				case TMeUrlTypeStickerSet.CONSTRUCTOR: return new TMeUrlTypeStickerSet(input);
				case TMeUrls.CONSTRUCTOR: return new TMeUrls(input);
				case TargetChatCurrent.CONSTRUCTOR: return new TargetChatCurrent(input);
				case TargetChatChosen.CONSTRUCTOR: return new TargetChatChosen(input);
				case TargetChatInternalLink.CONSTRUCTOR: return new TargetChatInternalLink(input);
				case TemporaryPasswordState.CONSTRUCTOR: return new TemporaryPasswordState(input);
				case TermsOfService.CONSTRUCTOR: return new TermsOfService(input);
				case TestBytes.CONSTRUCTOR: return new TestBytes(input);
				case TestInt.CONSTRUCTOR: return new TestInt(input);
				case TestString.CONSTRUCTOR: return new TestString(input);
				case TestVectorInt.CONSTRUCTOR: return new TestVectorInt(input);
				case TestVectorIntObject.CONSTRUCTOR: return new TestVectorIntObject(input);
				case TestVectorString.CONSTRUCTOR: return new TestVectorString(input);
				case TestVectorStringObject.CONSTRUCTOR: return new TestVectorStringObject(input);
				case Text.CONSTRUCTOR: return new Text(input);
				case TextEntities.CONSTRUCTOR: return new TextEntities(input);
				case TextEntity.CONSTRUCTOR: return new TextEntity(input);
				case TextEntityTypeMention.CONSTRUCTOR: return new TextEntityTypeMention(input);
				case TextEntityTypeHashtag.CONSTRUCTOR: return new TextEntityTypeHashtag(input);
				case TextEntityTypeCashtag.CONSTRUCTOR: return new TextEntityTypeCashtag(input);
				case TextEntityTypeBotCommand.CONSTRUCTOR: return new TextEntityTypeBotCommand(input);
				case TextEntityTypeUrl.CONSTRUCTOR: return new TextEntityTypeUrl(input);
				case TextEntityTypeEmailAddress.CONSTRUCTOR: return new TextEntityTypeEmailAddress(input);
				case TextEntityTypePhoneNumber.CONSTRUCTOR: return new TextEntityTypePhoneNumber(input);
				case TextEntityTypeBankCardNumber.CONSTRUCTOR: return new TextEntityTypeBankCardNumber(input);
				case TextEntityTypeBold.CONSTRUCTOR: return new TextEntityTypeBold(input);
				case TextEntityTypeItalic.CONSTRUCTOR: return new TextEntityTypeItalic(input);
				case TextEntityTypeUnderline.CONSTRUCTOR: return new TextEntityTypeUnderline(input);
				case TextEntityTypeStrikethrough.CONSTRUCTOR: return new TextEntityTypeStrikethrough(input);
				case TextEntityTypeSpoiler.CONSTRUCTOR: return new TextEntityTypeSpoiler(input);
				case TextEntityTypeCode.CONSTRUCTOR: return new TextEntityTypeCode(input);
				case TextEntityTypePre.CONSTRUCTOR: return new TextEntityTypePre(input);
				case TextEntityTypePreCode.CONSTRUCTOR: return new TextEntityTypePreCode(input);
				case TextEntityTypeTextUrl.CONSTRUCTOR: return new TextEntityTypeTextUrl(input);
				case TextEntityTypeMentionName.CONSTRUCTOR: return new TextEntityTypeMentionName(input);
				case TextEntityTypeCustomEmoji.CONSTRUCTOR: return new TextEntityTypeCustomEmoji(input);
				case TextEntityTypeMediaTimestamp.CONSTRUCTOR: return new TextEntityTypeMediaTimestamp(input);
				case TextParseModeMarkdown.CONSTRUCTOR: return new TextParseModeMarkdown(input);
				case TextParseModeHTML.CONSTRUCTOR: return new TextParseModeHTML(input);
				case ThemeParameters.CONSTRUCTOR: return new ThemeParameters(input);
				case ThemeSettings.CONSTRUCTOR: return new ThemeSettings(input);
				case Thumbnail.CONSTRUCTOR: return new Thumbnail(input);
				case ThumbnailFormatJpeg.CONSTRUCTOR: return new ThumbnailFormatJpeg(input);
				case ThumbnailFormatGif.CONSTRUCTOR: return new ThumbnailFormatGif(input);
				case ThumbnailFormatMpeg4.CONSTRUCTOR: return new ThumbnailFormatMpeg4(input);
				case ThumbnailFormatPng.CONSTRUCTOR: return new ThumbnailFormatPng(input);
				case ThumbnailFormatTgs.CONSTRUCTOR: return new ThumbnailFormatTgs(input);
				case ThumbnailFormatWebm.CONSTRUCTOR: return new ThumbnailFormatWebm(input);
				case ThumbnailFormatWebp.CONSTRUCTOR: return new ThumbnailFormatWebp(input);
				case TopChatCategoryUsers.CONSTRUCTOR: return new TopChatCategoryUsers(input);
				case TopChatCategoryBots.CONSTRUCTOR: return new TopChatCategoryBots(input);
				case TopChatCategoryGroups.CONSTRUCTOR: return new TopChatCategoryGroups(input);
				case TopChatCategoryChannels.CONSTRUCTOR: return new TopChatCategoryChannels(input);
				case TopChatCategoryInlineBots.CONSTRUCTOR: return new TopChatCategoryInlineBots(input);
				case TopChatCategoryCalls.CONSTRUCTOR: return new TopChatCategoryCalls(input);
				case TopChatCategoryForwardChats.CONSTRUCTOR: return new TopChatCategoryForwardChats(input);
				case TrendingStickerSets.CONSTRUCTOR: return new TrendingStickerSets(input);
				case UnreadReaction.CONSTRUCTOR: return new UnreadReaction(input);
				case UpdateAuthorizationState.CONSTRUCTOR: return new UpdateAuthorizationState(input);
				case UpdateNewMessage.CONSTRUCTOR: return new UpdateNewMessage(input);
				case UpdateMessageSendAcknowledged.CONSTRUCTOR: return new UpdateMessageSendAcknowledged(input);
				case UpdateMessageSendSucceeded.CONSTRUCTOR: return new UpdateMessageSendSucceeded(input);
				case UpdateMessageSendFailed.CONSTRUCTOR: return new UpdateMessageSendFailed(input);
				case UpdateMessageContent.CONSTRUCTOR: return new UpdateMessageContent(input);
				case UpdateMessageEdited.CONSTRUCTOR: return new UpdateMessageEdited(input);
				case UpdateMessageIsPinned.CONSTRUCTOR: return new UpdateMessageIsPinned(input);
				case UpdateMessageInteractionInfo.CONSTRUCTOR: return new UpdateMessageInteractionInfo(input);
				case UpdateMessageContentOpened.CONSTRUCTOR: return new UpdateMessageContentOpened(input);
				case UpdateMessageMentionRead.CONSTRUCTOR: return new UpdateMessageMentionRead(input);
				case UpdateMessageUnreadReactions.CONSTRUCTOR: return new UpdateMessageUnreadReactions(input);
				case UpdateMessageLiveLocationViewed.CONSTRUCTOR: return new UpdateMessageLiveLocationViewed(input);
				case UpdateNewChat.CONSTRUCTOR: return new UpdateNewChat(input);
				case UpdateChatTitle.CONSTRUCTOR: return new UpdateChatTitle(input);
				case UpdateChatPhoto.CONSTRUCTOR: return new UpdateChatPhoto(input);
				case UpdateChatPermissions.CONSTRUCTOR: return new UpdateChatPermissions(input);
				case UpdateChatLastMessage.CONSTRUCTOR: return new UpdateChatLastMessage(input);
				case UpdateChatPosition.CONSTRUCTOR: return new UpdateChatPosition(input);
				case UpdateChatReadInbox.CONSTRUCTOR: return new UpdateChatReadInbox(input);
				case UpdateChatReadOutbox.CONSTRUCTOR: return new UpdateChatReadOutbox(input);
				case UpdateChatActionBar.CONSTRUCTOR: return new UpdateChatActionBar(input);
				case UpdateChatAvailableReactions.CONSTRUCTOR: return new UpdateChatAvailableReactions(input);
				case UpdateChatDraftMessage.CONSTRUCTOR: return new UpdateChatDraftMessage(input);
				case UpdateChatMessageSender.CONSTRUCTOR: return new UpdateChatMessageSender(input);
				case UpdateChatMessageAutoDeleteTime.CONSTRUCTOR: return new UpdateChatMessageAutoDeleteTime(input);
				case UpdateChatNotificationSettings.CONSTRUCTOR: return new UpdateChatNotificationSettings(input);
				case UpdateChatPendingJoinRequests.CONSTRUCTOR: return new UpdateChatPendingJoinRequests(input);
				case UpdateChatReplyMarkup.CONSTRUCTOR: return new UpdateChatReplyMarkup(input);
				case UpdateChatBackground.CONSTRUCTOR: return new UpdateChatBackground(input);
				case UpdateChatTheme.CONSTRUCTOR: return new UpdateChatTheme(input);
				case UpdateChatUnreadMentionCount.CONSTRUCTOR: return new UpdateChatUnreadMentionCount(input);
				case UpdateChatUnreadReactionCount.CONSTRUCTOR: return new UpdateChatUnreadReactionCount(input);
				case UpdateChatVideoChat.CONSTRUCTOR: return new UpdateChatVideoChat(input);
				case UpdateChatDefaultDisableNotification.CONSTRUCTOR: return new UpdateChatDefaultDisableNotification(input);
				case UpdateChatHasProtectedContent.CONSTRUCTOR: return new UpdateChatHasProtectedContent(input);
				case UpdateChatIsTranslatable.CONSTRUCTOR: return new UpdateChatIsTranslatable(input);
				case UpdateChatIsMarkedAsUnread.CONSTRUCTOR: return new UpdateChatIsMarkedAsUnread(input);
				case UpdateChatIsBlocked.CONSTRUCTOR: return new UpdateChatIsBlocked(input);
				case UpdateChatHasScheduledMessages.CONSTRUCTOR: return new UpdateChatHasScheduledMessages(input);
				case UpdateChatFolders.CONSTRUCTOR: return new UpdateChatFolders(input);
				case UpdateChatOnlineMemberCount.CONSTRUCTOR: return new UpdateChatOnlineMemberCount(input);
				case UpdateForumTopicInfo.CONSTRUCTOR: return new UpdateForumTopicInfo(input);
				case UpdateScopeNotificationSettings.CONSTRUCTOR: return new UpdateScopeNotificationSettings(input);
				case UpdateNotification.CONSTRUCTOR: return new UpdateNotification(input);
				case UpdateNotificationGroup.CONSTRUCTOR: return new UpdateNotificationGroup(input);
				case UpdateActiveNotifications.CONSTRUCTOR: return new UpdateActiveNotifications(input);
				case UpdateHavePendingNotifications.CONSTRUCTOR: return new UpdateHavePendingNotifications(input);
				case UpdateDeleteMessages.CONSTRUCTOR: return new UpdateDeleteMessages(input);
				case UpdateChatAction.CONSTRUCTOR: return new UpdateChatAction(input);
				case UpdateUserStatus.CONSTRUCTOR: return new UpdateUserStatus(input);
				case UpdateUser.CONSTRUCTOR: return new UpdateUser(input);
				case UpdateAccessHash.CONSTRUCTOR: return new UpdateAccessHash(input);
				case UpdateBasicGroup.CONSTRUCTOR: return new UpdateBasicGroup(input);
				case UpdateSupergroup.CONSTRUCTOR: return new UpdateSupergroup(input);
				case UpdateSecretChat.CONSTRUCTOR: return new UpdateSecretChat(input);
				case UpdateUserFullInfo.CONSTRUCTOR: return new UpdateUserFullInfo(input);
				case UpdateBasicGroupFullInfo.CONSTRUCTOR: return new UpdateBasicGroupFullInfo(input);
				case UpdateSupergroupFullInfo.CONSTRUCTOR: return new UpdateSupergroupFullInfo(input);
				case UpdateServiceNotification.CONSTRUCTOR: return new UpdateServiceNotification(input);
				case UpdateFile.CONSTRUCTOR: return new UpdateFile(input);
				case UpdateFileGenerationStart.CONSTRUCTOR: return new UpdateFileGenerationStart(input);
				case UpdateFileGenerationStop.CONSTRUCTOR: return new UpdateFileGenerationStop(input);
				case UpdateFileDownloads.CONSTRUCTOR: return new UpdateFileDownloads(input);
				case UpdateFileAddedToDownloads.CONSTRUCTOR: return new UpdateFileAddedToDownloads(input);
				case UpdateFileDownload.CONSTRUCTOR: return new UpdateFileDownload(input);
				case UpdateFileRemovedFromDownloads.CONSTRUCTOR: return new UpdateFileRemovedFromDownloads(input);
				case UpdateCall.CONSTRUCTOR: return new UpdateCall(input);
				case UpdateGroupCall.CONSTRUCTOR: return new UpdateGroupCall(input);
				case UpdateGroupCallParticipant.CONSTRUCTOR: return new UpdateGroupCallParticipant(input);
				case UpdateNewCallSignalingData.CONSTRUCTOR: return new UpdateNewCallSignalingData(input);
				case UpdateUserPrivacySettingRules.CONSTRUCTOR: return new UpdateUserPrivacySettingRules(input);
				case UpdateUnreadMessageCount.CONSTRUCTOR: return new UpdateUnreadMessageCount(input);
				case UpdateUnreadChatCount.CONSTRUCTOR: return new UpdateUnreadChatCount(input);
				case UpdateOption.CONSTRUCTOR: return new UpdateOption(input);
				case UpdateStickerSet.CONSTRUCTOR: return new UpdateStickerSet(input);
				case UpdateInstalledStickerSets.CONSTRUCTOR: return new UpdateInstalledStickerSets(input);
				case UpdateTrendingStickerSets.CONSTRUCTOR: return new UpdateTrendingStickerSets(input);
				case UpdateRecentStickers.CONSTRUCTOR: return new UpdateRecentStickers(input);
				case UpdateFavoriteStickers.CONSTRUCTOR: return new UpdateFavoriteStickers(input);
				case UpdateSavedAnimations.CONSTRUCTOR: return new UpdateSavedAnimations(input);
				case UpdateSavedNotificationSounds.CONSTRUCTOR: return new UpdateSavedNotificationSounds(input);
				case UpdateSelectedBackground.CONSTRUCTOR: return new UpdateSelectedBackground(input);
				case UpdateChatThemes.CONSTRUCTOR: return new UpdateChatThemes(input);
				case UpdateLanguagePackStrings.CONSTRUCTOR: return new UpdateLanguagePackStrings(input);
				case UpdateConnectionState.CONSTRUCTOR: return new UpdateConnectionState(input);
				case UpdateTermsOfService.CONSTRUCTOR: return new UpdateTermsOfService(input);
				case UpdateUsersNearby.CONSTRUCTOR: return new UpdateUsersNearby(input);
				case UpdateAttachmentMenuBots.CONSTRUCTOR: return new UpdateAttachmentMenuBots(input);
				case UpdateWebAppMessageSent.CONSTRUCTOR: return new UpdateWebAppMessageSent(input);
				case UpdateActiveEmojiReactions.CONSTRUCTOR: return new UpdateActiveEmojiReactions(input);
				case UpdateDefaultReactionType.CONSTRUCTOR: return new UpdateDefaultReactionType(input);
				case UpdateDiceEmojis.CONSTRUCTOR: return new UpdateDiceEmojis(input);
				case UpdateAnimatedEmojiMessageClicked.CONSTRUCTOR: return new UpdateAnimatedEmojiMessageClicked(input);
				case UpdateAnimationSearchParameters.CONSTRUCTOR: return new UpdateAnimationSearchParameters(input);
				case UpdateSuggestedActions.CONSTRUCTOR: return new UpdateSuggestedActions(input);
				case UpdateAddChatMembersPrivacyForbidden.CONSTRUCTOR: return new UpdateAddChatMembersPrivacyForbidden(input);
				case UpdateAutosaveSettings.CONSTRUCTOR: return new UpdateAutosaveSettings(input);
				case UpdateNewInlineQuery.CONSTRUCTOR: return new UpdateNewInlineQuery(input);
				case UpdateNewChosenInlineResult.CONSTRUCTOR: return new UpdateNewChosenInlineResult(input);
				case UpdateNewCallbackQuery.CONSTRUCTOR: return new UpdateNewCallbackQuery(input);
				case UpdateNewInlineCallbackQuery.CONSTRUCTOR: return new UpdateNewInlineCallbackQuery(input);
				case UpdateNewShippingQuery.CONSTRUCTOR: return new UpdateNewShippingQuery(input);
				case UpdateNewPreCheckoutQuery.CONSTRUCTOR: return new UpdateNewPreCheckoutQuery(input);
				case UpdateNewCustomEvent.CONSTRUCTOR: return new UpdateNewCustomEvent(input);
				case UpdateNewCustomQuery.CONSTRUCTOR: return new UpdateNewCustomQuery(input);
				case UpdatePoll.CONSTRUCTOR: return new UpdatePoll(input);
				case UpdatePollAnswer.CONSTRUCTOR: return new UpdatePollAnswer(input);
				case UpdateChatMember.CONSTRUCTOR: return new UpdateChatMember(input);
				case UpdateNewChatJoinRequest.CONSTRUCTOR: return new UpdateNewChatJoinRequest(input);
				case Updates.CONSTRUCTOR: return new Updates(input);
				case User.CONSTRUCTOR: return new User(input);
				case UserFullInfo.CONSTRUCTOR: return new UserFullInfo(input);
				case UserLink.CONSTRUCTOR: return new UserLink(input);
				case UserPrivacySettingShowStatus.CONSTRUCTOR: return new UserPrivacySettingShowStatus(input);
				case UserPrivacySettingShowProfilePhoto.CONSTRUCTOR: return new UserPrivacySettingShowProfilePhoto(input);
				case UserPrivacySettingShowLinkInForwardedMessages.CONSTRUCTOR: return new UserPrivacySettingShowLinkInForwardedMessages(input);
				case UserPrivacySettingShowPhoneNumber.CONSTRUCTOR: return new UserPrivacySettingShowPhoneNumber(input);
				case UserPrivacySettingAllowChatInvites.CONSTRUCTOR: return new UserPrivacySettingAllowChatInvites(input);
				case UserPrivacySettingAllowCalls.CONSTRUCTOR: return new UserPrivacySettingAllowCalls(input);
				case UserPrivacySettingAllowPeerToPeerCalls.CONSTRUCTOR: return new UserPrivacySettingAllowPeerToPeerCalls(input);
				case UserPrivacySettingAllowFindingByPhoneNumber.CONSTRUCTOR: return new UserPrivacySettingAllowFindingByPhoneNumber(input);
				case UserPrivacySettingAllowPrivateVoiceAndVideoNoteMessages.CONSTRUCTOR: return new UserPrivacySettingAllowPrivateVoiceAndVideoNoteMessages(input);
				case UserPrivacySettingRuleAllowAll.CONSTRUCTOR: return new UserPrivacySettingRuleAllowAll(input);
				case UserPrivacySettingRuleAllowContacts.CONSTRUCTOR: return new UserPrivacySettingRuleAllowContacts(input);
				case UserPrivacySettingRuleAllowUsers.CONSTRUCTOR: return new UserPrivacySettingRuleAllowUsers(input);
				case UserPrivacySettingRuleAllowChatMembers.CONSTRUCTOR: return new UserPrivacySettingRuleAllowChatMembers(input);
				case UserPrivacySettingRuleRestrictAll.CONSTRUCTOR: return new UserPrivacySettingRuleRestrictAll(input);
				case UserPrivacySettingRuleRestrictContacts.CONSTRUCTOR: return new UserPrivacySettingRuleRestrictContacts(input);
				case UserPrivacySettingRuleRestrictUsers.CONSTRUCTOR: return new UserPrivacySettingRuleRestrictUsers(input);
				case UserPrivacySettingRuleRestrictChatMembers.CONSTRUCTOR: return new UserPrivacySettingRuleRestrictChatMembers(input);
				case UserPrivacySettingRules.CONSTRUCTOR: return new UserPrivacySettingRules(input);
				case UserStatusEmpty.CONSTRUCTOR: return new UserStatusEmpty(input);
				case UserStatusOnline.CONSTRUCTOR: return new UserStatusOnline(input);
				case UserStatusOffline.CONSTRUCTOR: return new UserStatusOffline(input);
				case UserStatusRecently.CONSTRUCTOR: return new UserStatusRecently(input);
				case UserStatusLastWeek.CONSTRUCTOR: return new UserStatusLastWeek(input);
				case UserStatusLastMonth.CONSTRUCTOR: return new UserStatusLastMonth(input);
				case UserSupportInfo.CONSTRUCTOR: return new UserSupportInfo(input);
				case UserTypeRegular.CONSTRUCTOR: return new UserTypeRegular(input);
				case UserTypeDeleted.CONSTRUCTOR: return new UserTypeDeleted(input);
				case UserTypeBot.CONSTRUCTOR: return new UserTypeBot(input);
				case UserTypeUnknown.CONSTRUCTOR: return new UserTypeUnknown(input);
				case Usernames.CONSTRUCTOR: return new Usernames(input);
				case Users.CONSTRUCTOR: return new Users(input);
				case ValidatedOrderInfo.CONSTRUCTOR: return new ValidatedOrderInfo(input);
				case VectorPathCommandLine.CONSTRUCTOR: return new VectorPathCommandLine(input);
				case VectorPathCommandCubicBezierCurve.CONSTRUCTOR: return new VectorPathCommandCubicBezierCurve(input);
				case Venue.CONSTRUCTOR: return new Venue(input);
				case Video.CONSTRUCTOR: return new Video(input);
				case VideoChat.CONSTRUCTOR: return new VideoChat(input);
				case VideoNote.CONSTRUCTOR: return new VideoNote(input);
				case VoiceNote.CONSTRUCTOR: return new VoiceNote(input);
				case WebApp.CONSTRUCTOR: return new WebApp(input);
				case WebAppInfo.CONSTRUCTOR: return new WebAppInfo(input);
				case WebPage.CONSTRUCTOR: return new WebPage(input);
				case WebPageInstantView.CONSTRUCTOR: return new WebPageInstantView(input);
				case AcceptCall.CONSTRUCTOR: return new AcceptCall(input);
				case AcceptTermsOfService.CONSTRUCTOR: return new AcceptTermsOfService(input);
				case AddApplicationChangelog.CONSTRUCTOR: return new AddApplicationChangelog(input);
				case AddChatFolderByInviteLink.CONSTRUCTOR: return new AddChatFolderByInviteLink(input);
				case AddChatMember.CONSTRUCTOR: return new AddChatMember(input);
				case AddChatMembers.CONSTRUCTOR: return new AddChatMembers(input);
				case AddChatToList.CONSTRUCTOR: return new AddChatToList(input);
				case AddContact.CONSTRUCTOR: return new AddContact(input);
				case AddCustomServerLanguagePack.CONSTRUCTOR: return new AddCustomServerLanguagePack(input);
				case AddFavoriteSticker.CONSTRUCTOR: return new AddFavoriteSticker(input);
				case AddFileToDownloads.CONSTRUCTOR: return new AddFileToDownloads(input);
				case AddLocalMessage.CONSTRUCTOR: return new AddLocalMessage(input);
				case AddLogMessage.CONSTRUCTOR: return new AddLogMessage(input);
				case AddMessageReaction.CONSTRUCTOR: return new AddMessageReaction(input);
				case AddNetworkStatistics.CONSTRUCTOR: return new AddNetworkStatistics(input);
				case AddProxy.CONSTRUCTOR: return new AddProxy(input);
				case AddRecentSticker.CONSTRUCTOR: return new AddRecentSticker(input);
				case AddRecentlyFoundChat.CONSTRUCTOR: return new AddRecentlyFoundChat(input);
				case AddSavedAnimation.CONSTRUCTOR: return new AddSavedAnimation(input);
				case AddSavedNotificationSound.CONSTRUCTOR: return new AddSavedNotificationSound(input);
				case AddStickerToSet.CONSTRUCTOR: return new AddStickerToSet(input);
				case AnswerCallbackQuery.CONSTRUCTOR: return new AnswerCallbackQuery(input);
				case AnswerCustomQuery.CONSTRUCTOR: return new AnswerCustomQuery(input);
				case AnswerInlineQuery.CONSTRUCTOR: return new AnswerInlineQuery(input);
				case AnswerPreCheckoutQuery.CONSTRUCTOR: return new AnswerPreCheckoutQuery(input);
				case AnswerShippingQuery.CONSTRUCTOR: return new AnswerShippingQuery(input);
				case AnswerWebAppQuery.CONSTRUCTOR: return new AnswerWebAppQuery(input);
				case AssignAppStoreTransaction.CONSTRUCTOR: return new AssignAppStoreTransaction(input);
				case AssignGooglePlayTransaction.CONSTRUCTOR: return new AssignGooglePlayTransaction(input);
				case BanChatMember.CONSTRUCTOR: return new BanChatMember(input);
				case BlockMessageSenderFromReplies.CONSTRUCTOR: return new BlockMessageSenderFromReplies(input);
				case CanPurchasePremium.CONSTRUCTOR: return new CanPurchasePremium(input);
				case CanTransferOwnership.CONSTRUCTOR: return new CanTransferOwnership(input);
				case CancelDownloadFile.CONSTRUCTOR: return new CancelDownloadFile(input);
				case CancelPasswordReset.CONSTRUCTOR: return new CancelPasswordReset(input);
				case CancelPreliminaryUploadFile.CONSTRUCTOR: return new CancelPreliminaryUploadFile(input);
				case ChangeImportedContacts.CONSTRUCTOR: return new ChangeImportedContacts(input);
				case ChangePhoneNumber.CONSTRUCTOR: return new ChangePhoneNumber(input);
				case ChangeStickerSet.CONSTRUCTOR: return new ChangeStickerSet(input);
				case CheckAuthenticationBotToken.CONSTRUCTOR: return new CheckAuthenticationBotToken(input);
				case CheckAuthenticationCode.CONSTRUCTOR: return new CheckAuthenticationCode(input);
				case CheckAuthenticationEmailCode.CONSTRUCTOR: return new CheckAuthenticationEmailCode(input);
				case CheckAuthenticationPassword.CONSTRUCTOR: return new CheckAuthenticationPassword(input);
				case CheckAuthenticationPasswordRecoveryCode.CONSTRUCTOR: return new CheckAuthenticationPasswordRecoveryCode(input);
				case CheckChangePhoneNumberCode.CONSTRUCTOR: return new CheckChangePhoneNumberCode(input);
				case CheckChatFolderInviteLink.CONSTRUCTOR: return new CheckChatFolderInviteLink(input);
				case CheckChatInviteLink.CONSTRUCTOR: return new CheckChatInviteLink(input);
				case CheckChatUsername.CONSTRUCTOR: return new CheckChatUsername(input);
				case CheckCreatedPublicChatsLimit.CONSTRUCTOR: return new CheckCreatedPublicChatsLimit(input);
				case CheckEmailAddressVerificationCode.CONSTRUCTOR: return new CheckEmailAddressVerificationCode(input);
				case CheckLoginEmailAddressCode.CONSTRUCTOR: return new CheckLoginEmailAddressCode(input);
				case CheckPasswordRecoveryCode.CONSTRUCTOR: return new CheckPasswordRecoveryCode(input);
				case CheckPhoneNumberConfirmationCode.CONSTRUCTOR: return new CheckPhoneNumberConfirmationCode(input);
				case CheckPhoneNumberVerificationCode.CONSTRUCTOR: return new CheckPhoneNumberVerificationCode(input);
				case CheckRecoveryEmailAddressCode.CONSTRUCTOR: return new CheckRecoveryEmailAddressCode(input);
				case CheckStickerSetName.CONSTRUCTOR: return new CheckStickerSetName(input);
				case CleanFileName.CONSTRUCTOR: return new CleanFileName(input);
				case ClearAllDraftMessages.CONSTRUCTOR: return new ClearAllDraftMessages(input);
				case ClearAutosaveSettingsExceptions.CONSTRUCTOR: return new ClearAutosaveSettingsExceptions(input);
				case ClearImportedContacts.CONSTRUCTOR: return new ClearImportedContacts(input);
				case ClearRecentEmojiStatuses.CONSTRUCTOR: return new ClearRecentEmojiStatuses(input);
				case ClearRecentReactions.CONSTRUCTOR: return new ClearRecentReactions(input);
				case ClearRecentStickers.CONSTRUCTOR: return new ClearRecentStickers(input);
				case ClearRecentlyFoundChats.CONSTRUCTOR: return new ClearRecentlyFoundChats(input);
				case ClickAnimatedEmojiMessage.CONSTRUCTOR: return new ClickAnimatedEmojiMessage(input);
				case ClickPremiumSubscriptionButton.CONSTRUCTOR: return new ClickPremiumSubscriptionButton(input);
				case Close.CONSTRUCTOR: return new Close(input);
				case CloseChat.CONSTRUCTOR: return new CloseChat(input);
				case CloseSecretChat.CONSTRUCTOR: return new CloseSecretChat(input);
				case CloseWebApp.CONSTRUCTOR: return new CloseWebApp(input);
				case ConfirmQrCodeAuthentication.CONSTRUCTOR: return new ConfirmQrCodeAuthentication(input);
				case CreateBasicGroupChat.CONSTRUCTOR: return new CreateBasicGroupChat(input);
				case CreateCall.CONSTRUCTOR: return new CreateCall(input);
				case CreateChatFolder.CONSTRUCTOR: return new CreateChatFolder(input);
				case CreateChatFolderInviteLink.CONSTRUCTOR: return new CreateChatFolderInviteLink(input);
				case CreateChatInviteLink.CONSTRUCTOR: return new CreateChatInviteLink(input);
				case CreateForumTopic.CONSTRUCTOR: return new CreateForumTopic(input);
				case CreateInvoiceLink.CONSTRUCTOR: return new CreateInvoiceLink(input);
				case CreateNewBasicGroupChat.CONSTRUCTOR: return new CreateNewBasicGroupChat(input);
				case CreateNewSecretChat.CONSTRUCTOR: return new CreateNewSecretChat(input);
				case CreateNewStickerSet.CONSTRUCTOR: return new CreateNewStickerSet(input);
				case CreateNewSupergroupChat.CONSTRUCTOR: return new CreateNewSupergroupChat(input);
				case CreatePrivateChat.CONSTRUCTOR: return new CreatePrivateChat(input);
				case CreateSecretChat.CONSTRUCTOR: return new CreateSecretChat(input);
				case CreateSupergroupChat.CONSTRUCTOR: return new CreateSupergroupChat(input);
				case CreateTemporaryPassword.CONSTRUCTOR: return new CreateTemporaryPassword(input);
				case CreateVideoChat.CONSTRUCTOR: return new CreateVideoChat(input);
				case DeleteAccount.CONSTRUCTOR: return new DeleteAccount(input);
				case DeleteAllCallMessages.CONSTRUCTOR: return new DeleteAllCallMessages(input);
				case DeleteAllRevokedChatInviteLinks.CONSTRUCTOR: return new DeleteAllRevokedChatInviteLinks(input);
				case DeleteChat.CONSTRUCTOR: return new DeleteChat(input);
				case DeleteChatFolder.CONSTRUCTOR: return new DeleteChatFolder(input);
				case DeleteChatFolderInviteLink.CONSTRUCTOR: return new DeleteChatFolderInviteLink(input);
				case DeleteChatHistory.CONSTRUCTOR: return new DeleteChatHistory(input);
				case DeleteChatMessagesByDate.CONSTRUCTOR: return new DeleteChatMessagesByDate(input);
				case DeleteChatMessagesBySender.CONSTRUCTOR: return new DeleteChatMessagesBySender(input);
				case DeleteChatReplyMarkup.CONSTRUCTOR: return new DeleteChatReplyMarkup(input);
				case DeleteCommands.CONSTRUCTOR: return new DeleteCommands(input);
				case DeleteFile.CONSTRUCTOR: return new DeleteFile(input);
				case DeleteForumTopic.CONSTRUCTOR: return new DeleteForumTopic(input);
				case DeleteLanguagePack.CONSTRUCTOR: return new DeleteLanguagePack(input);
				case DeleteMessages.CONSTRUCTOR: return new DeleteMessages(input);
				case DeletePassportElement.CONSTRUCTOR: return new DeletePassportElement(input);
				case DeleteProfilePhoto.CONSTRUCTOR: return new DeleteProfilePhoto(input);
				case DeleteRevokedChatInviteLink.CONSTRUCTOR: return new DeleteRevokedChatInviteLink(input);
				case DeleteSavedCredentials.CONSTRUCTOR: return new DeleteSavedCredentials(input);
				case DeleteSavedOrderInfo.CONSTRUCTOR: return new DeleteSavedOrderInfo(input);
				case DeleteStickerSet.CONSTRUCTOR: return new DeleteStickerSet(input);
				case Destroy.CONSTRUCTOR: return new Destroy(input);
				case DisableAllSupergroupUsernames.CONSTRUCTOR: return new DisableAllSupergroupUsernames(input);
				case DisableProxy.CONSTRUCTOR: return new DisableProxy(input);
				case DiscardCall.CONSTRUCTOR: return new DiscardCall(input);
				case DisconnectAllWebsites.CONSTRUCTOR: return new DisconnectAllWebsites(input);
				case DisconnectWebsite.CONSTRUCTOR: return new DisconnectWebsite(input);
				case DownloadFile.CONSTRUCTOR: return new DownloadFile(input);
				case EditChatFolder.CONSTRUCTOR: return new EditChatFolder(input);
				case EditChatFolderInviteLink.CONSTRUCTOR: return new EditChatFolderInviteLink(input);
				case EditChatInviteLink.CONSTRUCTOR: return new EditChatInviteLink(input);
				case EditCustomLanguagePackInfo.CONSTRUCTOR: return new EditCustomLanguagePackInfo(input);
				case EditForumTopic.CONSTRUCTOR: return new EditForumTopic(input);
				case EditInlineMessageCaption.CONSTRUCTOR: return new EditInlineMessageCaption(input);
				case EditInlineMessageLiveLocation.CONSTRUCTOR: return new EditInlineMessageLiveLocation(input);
				case EditInlineMessageMedia.CONSTRUCTOR: return new EditInlineMessageMedia(input);
				case EditInlineMessageReplyMarkup.CONSTRUCTOR: return new EditInlineMessageReplyMarkup(input);
				case EditInlineMessageText.CONSTRUCTOR: return new EditInlineMessageText(input);
				case EditMessageCaption.CONSTRUCTOR: return new EditMessageCaption(input);
				case EditMessageLiveLocation.CONSTRUCTOR: return new EditMessageLiveLocation(input);
				case EditMessageMedia.CONSTRUCTOR: return new EditMessageMedia(input);
				case EditMessageReplyMarkup.CONSTRUCTOR: return new EditMessageReplyMarkup(input);
				case EditMessageSchedulingState.CONSTRUCTOR: return new EditMessageSchedulingState(input);
				case EditMessageText.CONSTRUCTOR: return new EditMessageText(input);
				case EditProxy.CONSTRUCTOR: return new EditProxy(input);
				case EnableProxy.CONSTRUCTOR: return new EnableProxy(input);
				case EndGroupCall.CONSTRUCTOR: return new EndGroupCall(input);
				case EndGroupCallRecording.CONSTRUCTOR: return new EndGroupCallRecording(input);
				case EndGroupCallScreenSharing.CONSTRUCTOR: return new EndGroupCallScreenSharing(input);
				case FinishFileGeneration.CONSTRUCTOR: return new FinishFileGeneration(input);
				case ForwardMessages.CONSTRUCTOR: return new ForwardMessages(input);
				case GetAccountTtl.CONSTRUCTOR: return new GetAccountTtl(input);
				case GetActiveLiveLocationMessages.CONSTRUCTOR: return new GetActiveLiveLocationMessages(input);
				case GetActiveSessions.CONSTRUCTOR: return new GetActiveSessions(input);
				case GetAllPassportElements.CONSTRUCTOR: return new GetAllPassportElements(input);
				case GetAnimatedEmoji.CONSTRUCTOR: return new GetAnimatedEmoji(input);
				case GetApplicationConfig.CONSTRUCTOR: return new GetApplicationConfig(input);
				case GetApplicationDownloadLink.CONSTRUCTOR: return new GetApplicationDownloadLink(input);
				case GetArchivedStickerSets.CONSTRUCTOR: return new GetArchivedStickerSets(input);
				case GetAttachedStickerSets.CONSTRUCTOR: return new GetAttachedStickerSets(input);
				case GetAttachmentMenuBot.CONSTRUCTOR: return new GetAttachmentMenuBot(input);
				case GetAuthorizationState.CONSTRUCTOR: return new GetAuthorizationState(input);
				case GetAutoDownloadSettingsPresets.CONSTRUCTOR: return new GetAutoDownloadSettingsPresets(input);
				case GetAutosaveSettings.CONSTRUCTOR: return new GetAutosaveSettings(input);
				case GetBackgroundUrl.CONSTRUCTOR: return new GetBackgroundUrl(input);
				case GetBackgrounds.CONSTRUCTOR: return new GetBackgrounds(input);
				case GetBankCardInfo.CONSTRUCTOR: return new GetBankCardInfo(input);
				case GetBasicGroup.CONSTRUCTOR: return new GetBasicGroup(input);
				case GetBasicGroupFullInfo.CONSTRUCTOR: return new GetBasicGroupFullInfo(input);
				case GetBlockedMessageSenders.CONSTRUCTOR: return new GetBlockedMessageSenders(input);
				case GetBotInfoDescription.CONSTRUCTOR: return new GetBotInfoDescription(input);
				case GetBotInfoShortDescription.CONSTRUCTOR: return new GetBotInfoShortDescription(input);
				case GetBotName.CONSTRUCTOR: return new GetBotName(input);
				case GetCallbackQueryAnswer.CONSTRUCTOR: return new GetCallbackQueryAnswer(input);
				case GetCallbackQueryMessage.CONSTRUCTOR: return new GetCallbackQueryMessage(input);
				case GetChat.CONSTRUCTOR: return new GetChat(input);
				case GetChatAdministrators.CONSTRUCTOR: return new GetChatAdministrators(input);
				case GetChatAvailableMessageSenders.CONSTRUCTOR: return new GetChatAvailableMessageSenders(input);
				case GetChatEventLog.CONSTRUCTOR: return new GetChatEventLog(input);
				case GetChatFolder.CONSTRUCTOR: return new GetChatFolder(input);
				case GetChatFolderChatsToLeave.CONSTRUCTOR: return new GetChatFolderChatsToLeave(input);
				case GetChatFolderDefaultIconName.CONSTRUCTOR: return new GetChatFolderDefaultIconName(input);
				case GetChatFolderInviteLinks.CONSTRUCTOR: return new GetChatFolderInviteLinks(input);
				case GetChatFolderNewChats.CONSTRUCTOR: return new GetChatFolderNewChats(input);
				case GetChatHistory.CONSTRUCTOR: return new GetChatHistory(input);
				case GetChatInviteLink.CONSTRUCTOR: return new GetChatInviteLink(input);
				case GetChatInviteLinkCounts.CONSTRUCTOR: return new GetChatInviteLinkCounts(input);
				case GetChatInviteLinkMembers.CONSTRUCTOR: return new GetChatInviteLinkMembers(input);
				case GetChatInviteLinks.CONSTRUCTOR: return new GetChatInviteLinks(input);
				case GetChatJoinRequests.CONSTRUCTOR: return new GetChatJoinRequests(input);
				case GetChatListsToAddChat.CONSTRUCTOR: return new GetChatListsToAddChat(input);
				case GetChatMember.CONSTRUCTOR: return new GetChatMember(input);
				case GetChatMessageByDate.CONSTRUCTOR: return new GetChatMessageByDate(input);
				case GetChatMessageCalendar.CONSTRUCTOR: return new GetChatMessageCalendar(input);
				case GetChatMessageCount.CONSTRUCTOR: return new GetChatMessageCount(input);
				case GetChatMessagePosition.CONSTRUCTOR: return new GetChatMessagePosition(input);
				case GetChatNotificationSettingsExceptions.CONSTRUCTOR: return new GetChatNotificationSettingsExceptions(input);
				case GetChatPinnedMessage.CONSTRUCTOR: return new GetChatPinnedMessage(input);
				case GetChatScheduledMessages.CONSTRUCTOR: return new GetChatScheduledMessages(input);
				case GetChatSparseMessagePositions.CONSTRUCTOR: return new GetChatSparseMessagePositions(input);
				case GetChatSponsoredMessages.CONSTRUCTOR: return new GetChatSponsoredMessages(input);
				case GetChatStatistics.CONSTRUCTOR: return new GetChatStatistics(input);
				case GetChats.CONSTRUCTOR: return new GetChats(input);
				case GetChatsForChatFolderInviteLink.CONSTRUCTOR: return new GetChatsForChatFolderInviteLink(input);
				case GetCommands.CONSTRUCTOR: return new GetCommands(input);
				case GetConnectedWebsites.CONSTRUCTOR: return new GetConnectedWebsites(input);
				case GetContacts.CONSTRUCTOR: return new GetContacts(input);
				case GetCountries.CONSTRUCTOR: return new GetCountries(input);
				case GetCountryCode.CONSTRUCTOR: return new GetCountryCode(input);
				case GetCreatedPublicChats.CONSTRUCTOR: return new GetCreatedPublicChats(input);
				case GetCurrentState.CONSTRUCTOR: return new GetCurrentState(input);
				case GetCustomEmojiReactionAnimations.CONSTRUCTOR: return new GetCustomEmojiReactionAnimations(input);
				case GetCustomEmojiStickers.CONSTRUCTOR: return new GetCustomEmojiStickers(input);
				case GetDatabaseStatistics.CONSTRUCTOR: return new GetDatabaseStatistics(input);
				case GetDeepLinkInfo.CONSTRUCTOR: return new GetDeepLinkInfo(input);
				case GetDefaultChatPhotoCustomEmojiStickers.CONSTRUCTOR: return new GetDefaultChatPhotoCustomEmojiStickers(input);
				case GetDefaultEmojiStatuses.CONSTRUCTOR: return new GetDefaultEmojiStatuses(input);
				case GetDefaultMessageAutoDeleteTime.CONSTRUCTOR: return new GetDefaultMessageAutoDeleteTime(input);
				case GetDefaultProfilePhotoCustomEmojiStickers.CONSTRUCTOR: return new GetDefaultProfilePhotoCustomEmojiStickers(input);
				case GetEmojiCategories.CONSTRUCTOR: return new GetEmojiCategories(input);
				case GetEmojiReaction.CONSTRUCTOR: return new GetEmojiReaction(input);
				case GetEmojiSuggestionsUrl.CONSTRUCTOR: return new GetEmojiSuggestionsUrl(input);
				case GetExternalLink.CONSTRUCTOR: return new GetExternalLink(input);
				case GetExternalLinkInfo.CONSTRUCTOR: return new GetExternalLinkInfo(input);
				case GetFavoriteStickers.CONSTRUCTOR: return new GetFavoriteStickers(input);
				case GetFile.CONSTRUCTOR: return new GetFile(input);
				case GetFileDownloadedPrefixSize.CONSTRUCTOR: return new GetFileDownloadedPrefixSize(input);
				case GetFileExtension.CONSTRUCTOR: return new GetFileExtension(input);
				case GetFileMimeType.CONSTRUCTOR: return new GetFileMimeType(input);
				case GetForumTopic.CONSTRUCTOR: return new GetForumTopic(input);
				case GetForumTopicDefaultIcons.CONSTRUCTOR: return new GetForumTopicDefaultIcons(input);
				case GetForumTopicLink.CONSTRUCTOR: return new GetForumTopicLink(input);
				case GetForumTopics.CONSTRUCTOR: return new GetForumTopics(input);
				case GetGameHighScores.CONSTRUCTOR: return new GetGameHighScores(input);
				case GetGroupCall.CONSTRUCTOR: return new GetGroupCall(input);
				case GetGroupCallInviteLink.CONSTRUCTOR: return new GetGroupCallInviteLink(input);
				case GetGroupCallStreamSegment.CONSTRUCTOR: return new GetGroupCallStreamSegment(input);
				case GetGroupCallStreams.CONSTRUCTOR: return new GetGroupCallStreams(input);
				case GetGroupsInCommon.CONSTRUCTOR: return new GetGroupsInCommon(input);
				case GetImportedContactCount.CONSTRUCTOR: return new GetImportedContactCount(input);
				case GetInactiveSupergroupChats.CONSTRUCTOR: return new GetInactiveSupergroupChats(input);
				case GetInlineGameHighScores.CONSTRUCTOR: return new GetInlineGameHighScores(input);
				case GetInlineQueryResults.CONSTRUCTOR: return new GetInlineQueryResults(input);
				case GetInstalledStickerSets.CONSTRUCTOR: return new GetInstalledStickerSets(input);
				case GetInternalLink.CONSTRUCTOR: return new GetInternalLink(input);
				case GetInternalLinkType.CONSTRUCTOR: return new GetInternalLinkType(input);
				case GetJsonString.CONSTRUCTOR: return new GetJsonString(input);
				case GetJsonValue.CONSTRUCTOR: return new GetJsonValue(input);
				case GetLanguagePackInfo.CONSTRUCTOR: return new GetLanguagePackInfo(input);
				case GetLanguagePackString.CONSTRUCTOR: return new GetLanguagePackString(input);
				case GetLanguagePackStrings.CONSTRUCTOR: return new GetLanguagePackStrings(input);
				case GetLocalizationTargetInfo.CONSTRUCTOR: return new GetLocalizationTargetInfo(input);
				case GetLogStream.CONSTRUCTOR: return new GetLogStream(input);
				case GetLogTagVerbosityLevel.CONSTRUCTOR: return new GetLogTagVerbosityLevel(input);
				case GetLogTags.CONSTRUCTOR: return new GetLogTags(input);
				case GetLogVerbosityLevel.CONSTRUCTOR: return new GetLogVerbosityLevel(input);
				case GetLoginUrl.CONSTRUCTOR: return new GetLoginUrl(input);
				case GetLoginUrlInfo.CONSTRUCTOR: return new GetLoginUrlInfo(input);
				case GetMapThumbnailFile.CONSTRUCTOR: return new GetMapThumbnailFile(input);
				case GetMarkdownText.CONSTRUCTOR: return new GetMarkdownText(input);
				case GetMe.CONSTRUCTOR: return new GetMe(input);
				case GetMemoryStatistics.CONSTRUCTOR: return new GetMemoryStatistics(input);
				case GetMenuButton.CONSTRUCTOR: return new GetMenuButton(input);
				case GetMessage.CONSTRUCTOR: return new GetMessage(input);
				case GetMessageAddedReactions.CONSTRUCTOR: return new GetMessageAddedReactions(input);
				case GetMessageAvailableReactions.CONSTRUCTOR: return new GetMessageAvailableReactions(input);
				case GetMessageEmbeddingCode.CONSTRUCTOR: return new GetMessageEmbeddingCode(input);
				case GetMessageFileType.CONSTRUCTOR: return new GetMessageFileType(input);
				case GetMessageImportConfirmationText.CONSTRUCTOR: return new GetMessageImportConfirmationText(input);
				case GetMessageLink.CONSTRUCTOR: return new GetMessageLink(input);
				case GetMessageLinkInfo.CONSTRUCTOR: return new GetMessageLinkInfo(input);
				case GetMessageLocally.CONSTRUCTOR: return new GetMessageLocally(input);
				case GetMessagePublicForwards.CONSTRUCTOR: return new GetMessagePublicForwards(input);
				case GetMessageStatistics.CONSTRUCTOR: return new GetMessageStatistics(input);
				case GetMessageThread.CONSTRUCTOR: return new GetMessageThread(input);
				case GetMessageThreadHistory.CONSTRUCTOR: return new GetMessageThreadHistory(input);
				case GetMessageViewers.CONSTRUCTOR: return new GetMessageViewers(input);
				case GetMessages.CONSTRUCTOR: return new GetMessages(input);
				case GetNetworkStatistics.CONSTRUCTOR: return new GetNetworkStatistics(input);
				case GetOption.CONSTRUCTOR: return new GetOption(input);
				case GetPassportAuthorizationForm.CONSTRUCTOR: return new GetPassportAuthorizationForm(input);
				case GetPassportAuthorizationFormAvailableElements.CONSTRUCTOR: return new GetPassportAuthorizationFormAvailableElements(input);
				case GetPassportElement.CONSTRUCTOR: return new GetPassportElement(input);
				case GetPasswordState.CONSTRUCTOR: return new GetPasswordState(input);
				case GetPaymentForm.CONSTRUCTOR: return new GetPaymentForm(input);
				case GetPaymentReceipt.CONSTRUCTOR: return new GetPaymentReceipt(input);
				case GetPhoneNumberInfo.CONSTRUCTOR: return new GetPhoneNumberInfo(input);
				case GetPhoneNumberInfoSync.CONSTRUCTOR: return new GetPhoneNumberInfoSync(input);
				case GetPollVoters.CONSTRUCTOR: return new GetPollVoters(input);
				case GetPreferredCountryLanguage.CONSTRUCTOR: return new GetPreferredCountryLanguage(input);
				case GetPremiumFeatures.CONSTRUCTOR: return new GetPremiumFeatures(input);
				case GetPremiumLimit.CONSTRUCTOR: return new GetPremiumLimit(input);
				case GetPremiumState.CONSTRUCTOR: return new GetPremiumState(input);
				case GetPremiumStickerExamples.CONSTRUCTOR: return new GetPremiumStickerExamples(input);
				case GetPremiumStickers.CONSTRUCTOR: return new GetPremiumStickers(input);
				case GetProxies.CONSTRUCTOR: return new GetProxies(input);
				case GetProxyLink.CONSTRUCTOR: return new GetProxyLink(input);
				case GetPushReceiverId.CONSTRUCTOR: return new GetPushReceiverId(input);
				case GetRecentEmojiStatuses.CONSTRUCTOR: return new GetRecentEmojiStatuses(input);
				case GetRecentInlineBots.CONSTRUCTOR: return new GetRecentInlineBots(input);
				case GetRecentStickers.CONSTRUCTOR: return new GetRecentStickers(input);
				case GetRecentlyOpenedChats.CONSTRUCTOR: return new GetRecentlyOpenedChats(input);
				case GetRecentlyVisitedTMeUrls.CONSTRUCTOR: return new GetRecentlyVisitedTMeUrls(input);
				case GetRecommendedChatFolders.CONSTRUCTOR: return new GetRecommendedChatFolders(input);
				case GetRecoveryEmailAddress.CONSTRUCTOR: return new GetRecoveryEmailAddress(input);
				case GetRemoteFile.CONSTRUCTOR: return new GetRemoteFile(input);
				case GetRepliedMessage.CONSTRUCTOR: return new GetRepliedMessage(input);
				case GetSavedAnimations.CONSTRUCTOR: return new GetSavedAnimations(input);
				case GetSavedNotificationSound.CONSTRUCTOR: return new GetSavedNotificationSound(input);
				case GetSavedNotificationSounds.CONSTRUCTOR: return new GetSavedNotificationSounds(input);
				case GetSavedOrderInfo.CONSTRUCTOR: return new GetSavedOrderInfo(input);
				case GetScopeNotificationSettings.CONSTRUCTOR: return new GetScopeNotificationSettings(input);
				case GetSecretChat.CONSTRUCTOR: return new GetSecretChat(input);
				case GetStatisticalGraph.CONSTRUCTOR: return new GetStatisticalGraph(input);
				case GetStickerEmojis.CONSTRUCTOR: return new GetStickerEmojis(input);
				case GetStickerSet.CONSTRUCTOR: return new GetStickerSet(input);
				case GetStickers.CONSTRUCTOR: return new GetStickers(input);
				case GetStorageStatistics.CONSTRUCTOR: return new GetStorageStatistics(input);
				case GetStorageStatisticsFast.CONSTRUCTOR: return new GetStorageStatisticsFast(input);
				case GetSuggestedFileName.CONSTRUCTOR: return new GetSuggestedFileName(input);
				case GetSuggestedStickerSetName.CONSTRUCTOR: return new GetSuggestedStickerSetName(input);
				case GetSuitableDiscussionChats.CONSTRUCTOR: return new GetSuitableDiscussionChats(input);
				case GetSupergroup.CONSTRUCTOR: return new GetSupergroup(input);
				case GetSupergroupFullInfo.CONSTRUCTOR: return new GetSupergroupFullInfo(input);
				case GetSupergroupMembers.CONSTRUCTOR: return new GetSupergroupMembers(input);
				case GetSupportName.CONSTRUCTOR: return new GetSupportName(input);
				case GetSupportUser.CONSTRUCTOR: return new GetSupportUser(input);
				case GetTemporaryPasswordState.CONSTRUCTOR: return new GetTemporaryPasswordState(input);
				case GetTextEntities.CONSTRUCTOR: return new GetTextEntities(input);
				case GetThemeParametersJsonString.CONSTRUCTOR: return new GetThemeParametersJsonString(input);
				case GetThemedEmojiStatuses.CONSTRUCTOR: return new GetThemedEmojiStatuses(input);
				case GetTopChats.CONSTRUCTOR: return new GetTopChats(input);
				case GetTrendingStickerSets.CONSTRUCTOR: return new GetTrendingStickerSets(input);
				case GetUser.CONSTRUCTOR: return new GetUser(input);
				case GetUserFullInfo.CONSTRUCTOR: return new GetUserFullInfo(input);
				case GetUserLink.CONSTRUCTOR: return new GetUserLink(input);
				case GetUserPrivacySettingRules.CONSTRUCTOR: return new GetUserPrivacySettingRules(input);
				case GetUserProfilePhotos.CONSTRUCTOR: return new GetUserProfilePhotos(input);
				case GetUserSupportInfo.CONSTRUCTOR: return new GetUserSupportInfo(input);
				case GetVideoChatAvailableParticipants.CONSTRUCTOR: return new GetVideoChatAvailableParticipants(input);
				case GetVideoChatRtmpUrl.CONSTRUCTOR: return new GetVideoChatRtmpUrl(input);
				case GetWebAppLinkUrl.CONSTRUCTOR: return new GetWebAppLinkUrl(input);
				case GetWebAppUrl.CONSTRUCTOR: return new GetWebAppUrl(input);
				case GetWebPageInstantView.CONSTRUCTOR: return new GetWebPageInstantView(input);
				case GetWebPagePreview.CONSTRUCTOR: return new GetWebPagePreview(input);
				case HideSuggestedAction.CONSTRUCTOR: return new HideSuggestedAction(input);
				case ImportContacts.CONSTRUCTOR: return new ImportContacts(input);
				case ImportMessages.CONSTRUCTOR: return new ImportMessages(input);
				case InviteGroupCallParticipants.CONSTRUCTOR: return new InviteGroupCallParticipants(input);
				case JoinChat.CONSTRUCTOR: return new JoinChat(input);
				case JoinChatByInviteLink.CONSTRUCTOR: return new JoinChatByInviteLink(input);
				case JoinGroupCall.CONSTRUCTOR: return new JoinGroupCall(input);
				case LeaveChat.CONSTRUCTOR: return new LeaveChat(input);
				case LeaveGroupCall.CONSTRUCTOR: return new LeaveGroupCall(input);
				case LoadChats.CONSTRUCTOR: return new LoadChats(input);
				case LoadGroupCallParticipants.CONSTRUCTOR: return new LoadGroupCallParticipants(input);
				case LogOut.CONSTRUCTOR: return new LogOut(input);
				case OpenChat.CONSTRUCTOR: return new OpenChat(input);
				case OpenMessageContent.CONSTRUCTOR: return new OpenMessageContent(input);
				case OpenWebApp.CONSTRUCTOR: return new OpenWebApp(input);
				case OptimizeStorage.CONSTRUCTOR: return new OptimizeStorage(input);
				case ParseMarkdown.CONSTRUCTOR: return new ParseMarkdown(input);
				case ParseTextEntities.CONSTRUCTOR: return new ParseTextEntities(input);
				case PinChatMessage.CONSTRUCTOR: return new PinChatMessage(input);
				case PingProxy.CONSTRUCTOR: return new PingProxy(input);
				case PreliminaryUploadFile.CONSTRUCTOR: return new PreliminaryUploadFile(input);
				case ProcessChatFolderNewChats.CONSTRUCTOR: return new ProcessChatFolderNewChats(input);
				case ProcessChatJoinRequest.CONSTRUCTOR: return new ProcessChatJoinRequest(input);
				case ProcessChatJoinRequests.CONSTRUCTOR: return new ProcessChatJoinRequests(input);
				case ProcessPushNotification.CONSTRUCTOR: return new ProcessPushNotification(input);
				case RateSpeechRecognition.CONSTRUCTOR: return new RateSpeechRecognition(input);
				case ReadAllChatMentions.CONSTRUCTOR: return new ReadAllChatMentions(input);
				case ReadAllChatReactions.CONSTRUCTOR: return new ReadAllChatReactions(input);
				case ReadAllMessageThreadMentions.CONSTRUCTOR: return new ReadAllMessageThreadMentions(input);
				case ReadAllMessageThreadReactions.CONSTRUCTOR: return new ReadAllMessageThreadReactions(input);
				case ReadChatList.CONSTRUCTOR: return new ReadChatList(input);
				case ReadFilePart.CONSTRUCTOR: return new ReadFilePart(input);
				case RecognizeSpeech.CONSTRUCTOR: return new RecognizeSpeech(input);
				case RecoverAuthenticationPassword.CONSTRUCTOR: return new RecoverAuthenticationPassword(input);
				case RecoverPassword.CONSTRUCTOR: return new RecoverPassword(input);
				case RegisterDevice.CONSTRUCTOR: return new RegisterDevice(input);
				case RegisterUser.CONSTRUCTOR: return new RegisterUser(input);
				case RemoveAllFilesFromDownloads.CONSTRUCTOR: return new RemoveAllFilesFromDownloads(input);
				case RemoveBackground.CONSTRUCTOR: return new RemoveBackground(input);
				case RemoveChatActionBar.CONSTRUCTOR: return new RemoveChatActionBar(input);
				case RemoveContacts.CONSTRUCTOR: return new RemoveContacts(input);
				case RemoveFavoriteSticker.CONSTRUCTOR: return new RemoveFavoriteSticker(input);
				case RemoveFileFromDownloads.CONSTRUCTOR: return new RemoveFileFromDownloads(input);
				case RemoveMessageReaction.CONSTRUCTOR: return new RemoveMessageReaction(input);
				case RemoveNotification.CONSTRUCTOR: return new RemoveNotification(input);
				case RemoveNotificationGroup.CONSTRUCTOR: return new RemoveNotificationGroup(input);
				case RemoveProxy.CONSTRUCTOR: return new RemoveProxy(input);
				case RemoveRecentHashtag.CONSTRUCTOR: return new RemoveRecentHashtag(input);
				case RemoveRecentSticker.CONSTRUCTOR: return new RemoveRecentSticker(input);
				case RemoveRecentlyFoundChat.CONSTRUCTOR: return new RemoveRecentlyFoundChat(input);
				case RemoveSavedAnimation.CONSTRUCTOR: return new RemoveSavedAnimation(input);
				case RemoveSavedNotificationSound.CONSTRUCTOR: return new RemoveSavedNotificationSound(input);
				case RemoveStickerFromSet.CONSTRUCTOR: return new RemoveStickerFromSet(input);
				case RemoveTopChat.CONSTRUCTOR: return new RemoveTopChat(input);
				case ReorderActiveBotUsernames.CONSTRUCTOR: return new ReorderActiveBotUsernames(input);
				case ReorderActiveUsernames.CONSTRUCTOR: return new ReorderActiveUsernames(input);
				case ReorderChatFolders.CONSTRUCTOR: return new ReorderChatFolders(input);
				case ReorderInstalledStickerSets.CONSTRUCTOR: return new ReorderInstalledStickerSets(input);
				case ReorderSupergroupActiveUsernames.CONSTRUCTOR: return new ReorderSupergroupActiveUsernames(input);
				case ReplacePrimaryChatInviteLink.CONSTRUCTOR: return new ReplacePrimaryChatInviteLink(input);
				case ReplaceVideoChatRtmpUrl.CONSTRUCTOR: return new ReplaceVideoChatRtmpUrl(input);
				case ReportChat.CONSTRUCTOR: return new ReportChat(input);
				case ReportChatPhoto.CONSTRUCTOR: return new ReportChatPhoto(input);
				case ReportMessageReactions.CONSTRUCTOR: return new ReportMessageReactions(input);
				case ReportSupergroupAntiSpamFalsePositive.CONSTRUCTOR: return new ReportSupergroupAntiSpamFalsePositive(input);
				case ReportSupergroupSpam.CONSTRUCTOR: return new ReportSupergroupSpam(input);
				case RequestAuthenticationPasswordRecovery.CONSTRUCTOR: return new RequestAuthenticationPasswordRecovery(input);
				case RequestPasswordRecovery.CONSTRUCTOR: return new RequestPasswordRecovery(input);
				case RequestQrCodeAuthentication.CONSTRUCTOR: return new RequestQrCodeAuthentication(input);
				case ResendAuthenticationCode.CONSTRUCTOR: return new ResendAuthenticationCode(input);
				case ResendChangePhoneNumberCode.CONSTRUCTOR: return new ResendChangePhoneNumberCode(input);
				case ResendEmailAddressVerificationCode.CONSTRUCTOR: return new ResendEmailAddressVerificationCode(input);
				case ResendLoginEmailAddressCode.CONSTRUCTOR: return new ResendLoginEmailAddressCode(input);
				case ResendMessages.CONSTRUCTOR: return new ResendMessages(input);
				case ResendPhoneNumberConfirmationCode.CONSTRUCTOR: return new ResendPhoneNumberConfirmationCode(input);
				case ResendPhoneNumberVerificationCode.CONSTRUCTOR: return new ResendPhoneNumberVerificationCode(input);
				case ResendRecoveryEmailAddressCode.CONSTRUCTOR: return new ResendRecoveryEmailAddressCode(input);
				case ResetAllNotificationSettings.CONSTRUCTOR: return new ResetAllNotificationSettings(input);
				case ResetAuthenticationEmailAddress.CONSTRUCTOR: return new ResetAuthenticationEmailAddress(input);
				case ResetBackgrounds.CONSTRUCTOR: return new ResetBackgrounds(input);
				case ResetNetworkStatistics.CONSTRUCTOR: return new ResetNetworkStatistics(input);
				case ResetPassword.CONSTRUCTOR: return new ResetPassword(input);
				case RevokeChatInviteLink.CONSTRUCTOR: return new RevokeChatInviteLink(input);
				case RevokeGroupCallInviteLink.CONSTRUCTOR: return new RevokeGroupCallInviteLink(input);
				case SaveApplicationLogEvent.CONSTRUCTOR: return new SaveApplicationLogEvent(input);
				case SearchBackground.CONSTRUCTOR: return new SearchBackground(input);
				case SearchCallMessages.CONSTRUCTOR: return new SearchCallMessages(input);
				case SearchChatMembers.CONSTRUCTOR: return new SearchChatMembers(input);
				case SearchChatMessages.CONSTRUCTOR: return new SearchChatMessages(input);
				case SearchChatRecentLocationMessages.CONSTRUCTOR: return new SearchChatRecentLocationMessages(input);
				case SearchChats.CONSTRUCTOR: return new SearchChats(input);
				case SearchChatsNearby.CONSTRUCTOR: return new SearchChatsNearby(input);
				case SearchChatsOnServer.CONSTRUCTOR: return new SearchChatsOnServer(input);
				case SearchContacts.CONSTRUCTOR: return new SearchContacts(input);
				case SearchEmojis.CONSTRUCTOR: return new SearchEmojis(input);
				case SearchFileDownloads.CONSTRUCTOR: return new SearchFileDownloads(input);
				case SearchHashtags.CONSTRUCTOR: return new SearchHashtags(input);
				case SearchInstalledStickerSets.CONSTRUCTOR: return new SearchInstalledStickerSets(input);
				case SearchMessages.CONSTRUCTOR: return new SearchMessages(input);
				case SearchOutgoingDocumentMessages.CONSTRUCTOR: return new SearchOutgoingDocumentMessages(input);
				case SearchPublicChat.CONSTRUCTOR: return new SearchPublicChat(input);
				case SearchPublicChats.CONSTRUCTOR: return new SearchPublicChats(input);
				case SearchSecretMessages.CONSTRUCTOR: return new SearchSecretMessages(input);
				case SearchStickerSet.CONSTRUCTOR: return new SearchStickerSet(input);
				case SearchStickerSets.CONSTRUCTOR: return new SearchStickerSets(input);
				case SearchStickers.CONSTRUCTOR: return new SearchStickers(input);
				case SearchUserByPhoneNumber.CONSTRUCTOR: return new SearchUserByPhoneNumber(input);
				case SearchUserByToken.CONSTRUCTOR: return new SearchUserByToken(input);
				case SearchWebApp.CONSTRUCTOR: return new SearchWebApp(input);
				case SendAuthenticationFirebaseSms.CONSTRUCTOR: return new SendAuthenticationFirebaseSms(input);
				case SendBotStartMessage.CONSTRUCTOR: return new SendBotStartMessage(input);
				case SendCallDebugInformation.CONSTRUCTOR: return new SendCallDebugInformation(input);
				case SendCallLog.CONSTRUCTOR: return new SendCallLog(input);
				case SendCallRating.CONSTRUCTOR: return new SendCallRating(input);
				case SendCallSignalingData.CONSTRUCTOR: return new SendCallSignalingData(input);
				case SendChatAction.CONSTRUCTOR: return new SendChatAction(input);
				case SendChatScreenshotTakenNotification.CONSTRUCTOR: return new SendChatScreenshotTakenNotification(input);
				case SendCustomRequest.CONSTRUCTOR: return new SendCustomRequest(input);
				case SendEmailAddressVerificationCode.CONSTRUCTOR: return new SendEmailAddressVerificationCode(input);
				case SendInlineQueryResultMessage.CONSTRUCTOR: return new SendInlineQueryResultMessage(input);
				case SendMessage.CONSTRUCTOR: return new SendMessage(input);
				case SendMessageAlbum.CONSTRUCTOR: return new SendMessageAlbum(input);
				case SendPassportAuthorizationForm.CONSTRUCTOR: return new SendPassportAuthorizationForm(input);
				case SendPaymentForm.CONSTRUCTOR: return new SendPaymentForm(input);
				case SendPhoneNumberConfirmationCode.CONSTRUCTOR: return new SendPhoneNumberConfirmationCode(input);
				case SendPhoneNumberVerificationCode.CONSTRUCTOR: return new SendPhoneNumberVerificationCode(input);
				case SendWebAppData.CONSTRUCTOR: return new SendWebAppData(input);
				case SetAccountTtl.CONSTRUCTOR: return new SetAccountTtl(input);
				case SetAlarm.CONSTRUCTOR: return new SetAlarm(input);
				case SetAuthenticationEmailAddress.CONSTRUCTOR: return new SetAuthenticationEmailAddress(input);
				case SetAuthenticationPhoneNumber.CONSTRUCTOR: return new SetAuthenticationPhoneNumber(input);
				case SetAutoDownloadSettings.CONSTRUCTOR: return new SetAutoDownloadSettings(input);
				case SetAutosaveSettings.CONSTRUCTOR: return new SetAutosaveSettings(input);
				case SetBackground.CONSTRUCTOR: return new SetBackground(input);
				case SetBio.CONSTRUCTOR: return new SetBio(input);
				case SetBotInfoDescription.CONSTRUCTOR: return new SetBotInfoDescription(input);
				case SetBotInfoShortDescription.CONSTRUCTOR: return new SetBotInfoShortDescription(input);
				case SetBotName.CONSTRUCTOR: return new SetBotName(input);
				case SetBotProfilePhoto.CONSTRUCTOR: return new SetBotProfilePhoto(input);
				case SetBotUpdatesStatus.CONSTRUCTOR: return new SetBotUpdatesStatus(input);
				case SetChatAvailableReactions.CONSTRUCTOR: return new SetChatAvailableReactions(input);
				case SetChatBackground.CONSTRUCTOR: return new SetChatBackground(input);
				case SetChatClientData.CONSTRUCTOR: return new SetChatClientData(input);
				case SetChatDescription.CONSTRUCTOR: return new SetChatDescription(input);
				case SetChatDiscussionGroup.CONSTRUCTOR: return new SetChatDiscussionGroup(input);
				case SetChatDraftMessage.CONSTRUCTOR: return new SetChatDraftMessage(input);
				case SetChatLocation.CONSTRUCTOR: return new SetChatLocation(input);
				case SetChatMemberStatus.CONSTRUCTOR: return new SetChatMemberStatus(input);
				case SetChatMessageAutoDeleteTime.CONSTRUCTOR: return new SetChatMessageAutoDeleteTime(input);
				case SetChatMessageSender.CONSTRUCTOR: return new SetChatMessageSender(input);
				case SetChatNotificationSettings.CONSTRUCTOR: return new SetChatNotificationSettings(input);
				case SetChatPermissions.CONSTRUCTOR: return new SetChatPermissions(input);
				case SetChatPhoto.CONSTRUCTOR: return new SetChatPhoto(input);
				case SetChatSlowModeDelay.CONSTRUCTOR: return new SetChatSlowModeDelay(input);
				case SetChatTheme.CONSTRUCTOR: return new SetChatTheme(input);
				case SetChatTitle.CONSTRUCTOR: return new SetChatTitle(input);
				case SetCommands.CONSTRUCTOR: return new SetCommands(input);
				case SetCustomEmojiStickerSetThumbnail.CONSTRUCTOR: return new SetCustomEmojiStickerSetThumbnail(input);
				case SetCustomLanguagePack.CONSTRUCTOR: return new SetCustomLanguagePack(input);
				case SetCustomLanguagePackString.CONSTRUCTOR: return new SetCustomLanguagePackString(input);
				case SetDatabaseEncryptionKey.CONSTRUCTOR: return new SetDatabaseEncryptionKey(input);
				case SetDefaultChannelAdministratorRights.CONSTRUCTOR: return new SetDefaultChannelAdministratorRights(input);
				case SetDefaultGroupAdministratorRights.CONSTRUCTOR: return new SetDefaultGroupAdministratorRights(input);
				case SetDefaultMessageAutoDeleteTime.CONSTRUCTOR: return new SetDefaultMessageAutoDeleteTime(input);
				case SetDefaultReactionType.CONSTRUCTOR: return new SetDefaultReactionType(input);
				case SetEmojiStatus.CONSTRUCTOR: return new SetEmojiStatus(input);
				case SetFileGenerationProgress.CONSTRUCTOR: return new SetFileGenerationProgress(input);
				case SetForumTopicNotificationSettings.CONSTRUCTOR: return new SetForumTopicNotificationSettings(input);
				case SetGameScore.CONSTRUCTOR: return new SetGameScore(input);
				case SetGroupCallParticipantIsSpeaking.CONSTRUCTOR: return new SetGroupCallParticipantIsSpeaking(input);
				case SetGroupCallParticipantVolumeLevel.CONSTRUCTOR: return new SetGroupCallParticipantVolumeLevel(input);
				case SetGroupCallTitle.CONSTRUCTOR: return new SetGroupCallTitle(input);
				case SetInactiveSessionTtl.CONSTRUCTOR: return new SetInactiveSessionTtl(input);
				case SetInlineGameScore.CONSTRUCTOR: return new SetInlineGameScore(input);
				case SetLocation.CONSTRUCTOR: return new SetLocation(input);
				case SetLogStream.CONSTRUCTOR: return new SetLogStream(input);
				case SetLogTagVerbosityLevel.CONSTRUCTOR: return new SetLogTagVerbosityLevel(input);
				case SetLogVerbosityLevel.CONSTRUCTOR: return new SetLogVerbosityLevel(input);
				case SetLoginEmailAddress.CONSTRUCTOR: return new SetLoginEmailAddress(input);
				case SetMenuButton.CONSTRUCTOR: return new SetMenuButton(input);
				case SetName.CONSTRUCTOR: return new SetName(input);
				case SetNetworkType.CONSTRUCTOR: return new SetNetworkType(input);
				case SetOption.CONSTRUCTOR: return new SetOption(input);
				case SetPassportElement.CONSTRUCTOR: return new SetPassportElement(input);
				case SetPassportElementErrors.CONSTRUCTOR: return new SetPassportElementErrors(input);
				case SetPassword.CONSTRUCTOR: return new SetPassword(input);
				case SetPinnedChats.CONSTRUCTOR: return new SetPinnedChats(input);
				case SetPinnedForumTopics.CONSTRUCTOR: return new SetPinnedForumTopics(input);
				case SetPollAnswer.CONSTRUCTOR: return new SetPollAnswer(input);
				case SetProfilePhoto.CONSTRUCTOR: return new SetProfilePhoto(input);
				case SetRecoveryEmailAddress.CONSTRUCTOR: return new SetRecoveryEmailAddress(input);
				case SetScopeNotificationSettings.CONSTRUCTOR: return new SetScopeNotificationSettings(input);
				case SetStickerEmojis.CONSTRUCTOR: return new SetStickerEmojis(input);
				case SetStickerKeywords.CONSTRUCTOR: return new SetStickerKeywords(input);
				case SetStickerMaskPosition.CONSTRUCTOR: return new SetStickerMaskPosition(input);
				case SetStickerPositionInSet.CONSTRUCTOR: return new SetStickerPositionInSet(input);
				case SetStickerSetThumbnail.CONSTRUCTOR: return new SetStickerSetThumbnail(input);
				case SetStickerSetTitle.CONSTRUCTOR: return new SetStickerSetTitle(input);
				case SetSupergroupStickerSet.CONSTRUCTOR: return new SetSupergroupStickerSet(input);
				case SetSupergroupUsername.CONSTRUCTOR: return new SetSupergroupUsername(input);
				case SetTdlibParameters.CONSTRUCTOR: return new SetTdlibParameters(input);
				case SetUserPersonalProfilePhoto.CONSTRUCTOR: return new SetUserPersonalProfilePhoto(input);
				case SetUserPrivacySettingRules.CONSTRUCTOR: return new SetUserPrivacySettingRules(input);
				case SetUserSupportInfo.CONSTRUCTOR: return new SetUserSupportInfo(input);
				case SetUsername.CONSTRUCTOR: return new SetUsername(input);
				case SetVideoChatDefaultParticipant.CONSTRUCTOR: return new SetVideoChatDefaultParticipant(input);
				case ShareChatWithBot.CONSTRUCTOR: return new ShareChatWithBot(input);
				case SharePhoneNumber.CONSTRUCTOR: return new SharePhoneNumber(input);
				case ShareUserWithBot.CONSTRUCTOR: return new ShareUserWithBot(input);
				case StartGroupCallRecording.CONSTRUCTOR: return new StartGroupCallRecording(input);
				case StartGroupCallScreenSharing.CONSTRUCTOR: return new StartGroupCallScreenSharing(input);
				case StartScheduledGroupCall.CONSTRUCTOR: return new StartScheduledGroupCall(input);
				case StopPoll.CONSTRUCTOR: return new StopPoll(input);
				case SuggestUserProfilePhoto.CONSTRUCTOR: return new SuggestUserProfilePhoto(input);
				case SynchronizeLanguagePack.CONSTRUCTOR: return new SynchronizeLanguagePack(input);
				case TerminateAllOtherSessions.CONSTRUCTOR: return new TerminateAllOtherSessions(input);
				case TerminateSession.CONSTRUCTOR: return new TerminateSession(input);
				case TestCallBytes.CONSTRUCTOR: return new TestCallBytes(input);
				case TestCallEmpty.CONSTRUCTOR: return new TestCallEmpty(input);
				case TestCallString.CONSTRUCTOR: return new TestCallString(input);
				case TestCallVectorInt.CONSTRUCTOR: return new TestCallVectorInt(input);
				case TestCallVectorIntObject.CONSTRUCTOR: return new TestCallVectorIntObject(input);
				case TestCallVectorString.CONSTRUCTOR: return new TestCallVectorString(input);
				case TestCallVectorStringObject.CONSTRUCTOR: return new TestCallVectorStringObject(input);
				case TestGetDifference.CONSTRUCTOR: return new TestGetDifference(input);
				case TestNetwork.CONSTRUCTOR: return new TestNetwork(input);
				case TestProxy.CONSTRUCTOR: return new TestProxy(input);
				case TestReturnError.CONSTRUCTOR: return new TestReturnError(input);
				case TestSquareInt.CONSTRUCTOR: return new TestSquareInt(input);
				case TestUseUpdate.CONSTRUCTOR: return new TestUseUpdate(input);
				case ToggleAllDownloadsArePaused.CONSTRUCTOR: return new ToggleAllDownloadsArePaused(input);
				case ToggleBotIsAddedToAttachmentMenu.CONSTRUCTOR: return new ToggleBotIsAddedToAttachmentMenu(input);
				case ToggleBotUsernameIsActive.CONSTRUCTOR: return new ToggleBotUsernameIsActive(input);
				case ToggleChatDefaultDisableNotification.CONSTRUCTOR: return new ToggleChatDefaultDisableNotification(input);
				case ToggleChatHasProtectedContent.CONSTRUCTOR: return new ToggleChatHasProtectedContent(input);
				case ToggleChatIsMarkedAsUnread.CONSTRUCTOR: return new ToggleChatIsMarkedAsUnread(input);
				case ToggleChatIsPinned.CONSTRUCTOR: return new ToggleChatIsPinned(input);
				case ToggleChatIsTranslatable.CONSTRUCTOR: return new ToggleChatIsTranslatable(input);
				case ToggleDownloadIsPaused.CONSTRUCTOR: return new ToggleDownloadIsPaused(input);
				case ToggleForumTopicIsClosed.CONSTRUCTOR: return new ToggleForumTopicIsClosed(input);
				case ToggleForumTopicIsPinned.CONSTRUCTOR: return new ToggleForumTopicIsPinned(input);
				case ToggleGeneralForumTopicIsHidden.CONSTRUCTOR: return new ToggleGeneralForumTopicIsHidden(input);
				case ToggleGroupCallEnabledStartNotification.CONSTRUCTOR: return new ToggleGroupCallEnabledStartNotification(input);
				case ToggleGroupCallIsMyVideoEnabled.CONSTRUCTOR: return new ToggleGroupCallIsMyVideoEnabled(input);
				case ToggleGroupCallIsMyVideoPaused.CONSTRUCTOR: return new ToggleGroupCallIsMyVideoPaused(input);
				case ToggleGroupCallMuteNewParticipants.CONSTRUCTOR: return new ToggleGroupCallMuteNewParticipants(input);
				case ToggleGroupCallParticipantIsHandRaised.CONSTRUCTOR: return new ToggleGroupCallParticipantIsHandRaised(input);
				case ToggleGroupCallParticipantIsMuted.CONSTRUCTOR: return new ToggleGroupCallParticipantIsMuted(input);
				case ToggleGroupCallScreenSharingIsPaused.CONSTRUCTOR: return new ToggleGroupCallScreenSharingIsPaused(input);
				case ToggleMessageSenderIsBlocked.CONSTRUCTOR: return new ToggleMessageSenderIsBlocked(input);
				case ToggleSessionCanAcceptCalls.CONSTRUCTOR: return new ToggleSessionCanAcceptCalls(input);
				case ToggleSessionCanAcceptSecretChats.CONSTRUCTOR: return new ToggleSessionCanAcceptSecretChats(input);
				case ToggleSupergroupHasAggressiveAntiSpamEnabled.CONSTRUCTOR: return new ToggleSupergroupHasAggressiveAntiSpamEnabled(input);
				case ToggleSupergroupHasHiddenMembers.CONSTRUCTOR: return new ToggleSupergroupHasHiddenMembers(input);
				case ToggleSupergroupIsAllHistoryAvailable.CONSTRUCTOR: return new ToggleSupergroupIsAllHistoryAvailable(input);
				case ToggleSupergroupIsBroadcastGroup.CONSTRUCTOR: return new ToggleSupergroupIsBroadcastGroup(input);
				case ToggleSupergroupIsForum.CONSTRUCTOR: return new ToggleSupergroupIsForum(input);
				case ToggleSupergroupJoinByRequest.CONSTRUCTOR: return new ToggleSupergroupJoinByRequest(input);
				case ToggleSupergroupJoinToSendMessages.CONSTRUCTOR: return new ToggleSupergroupJoinToSendMessages(input);
				case ToggleSupergroupSignMessages.CONSTRUCTOR: return new ToggleSupergroupSignMessages(input);
				case ToggleSupergroupUsernameIsActive.CONSTRUCTOR: return new ToggleSupergroupUsernameIsActive(input);
				case ToggleUsernameIsActive.CONSTRUCTOR: return new ToggleUsernameIsActive(input);
				case TransferChatOwnership.CONSTRUCTOR: return new TransferChatOwnership(input);
				case TranslateMessageText.CONSTRUCTOR: return new TranslateMessageText(input);
				case TranslateText.CONSTRUCTOR: return new TranslateText(input);
				case UnpinAllChatMessages.CONSTRUCTOR: return new UnpinAllChatMessages(input);
				case UnpinAllMessageThreadMessages.CONSTRUCTOR: return new UnpinAllMessageThreadMessages(input);
				case UnpinChatMessage.CONSTRUCTOR: return new UnpinChatMessage(input);
				case UpgradeBasicGroupChatToSupergroupChat.CONSTRUCTOR: return new UpgradeBasicGroupChatToSupergroupChat(input);
				case UploadStickerFile.CONSTRUCTOR: return new UploadStickerFile(input);
				case ValidateOrderInfo.CONSTRUCTOR: return new ValidateOrderInfo(input);
				case ViewMessages.CONSTRUCTOR: return new ViewMessages(input);
				case ViewPremiumFeature.CONSTRUCTOR: return new ViewPremiumFeature(input);
				case ViewTrendingStickerSets.CONSTRUCTOR: return new ViewTrendingStickerSets(input);
				case WriteGeneratedFilePart.CONSTRUCTOR: return new WriteGeneratedFilePart(input);
				default: {
					throw new UnsupportedOperationException();
				}
			}
		}
	}

	/**
	 * This class is an abstract base class.
	 * Represents the type of an access hash. The following types are
	 * possible: user, channel.
	**/
	public abstract static class AccessHashType extends Object {

		/**
		 * Default class constructor.
		**/
		public AccessHashType() {}

	}

	/**
	 * This class is an abstract base class.
	 * Provides information about the method by which an authentication code
	 * is delivered to the user.
	**/
	public abstract static class AuthenticationCodeType extends Object {

		/**
		 * Default class constructor.
		**/
		public AuthenticationCodeType() {}

	}

	/**
	 * This class is an abstract base class.
	 * Represents the current authorization state of the TDLib client.
	**/
	public abstract static class AuthorizationState extends Object {

		/**
		 * Default class constructor.
		**/
		public AuthorizationState() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes scope of autosave settings.
	**/
	public abstract static class AutosaveSettingsScope extends Object {

		/**
		 * Default class constructor.
		**/
		public AutosaveSettingsScope() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes a fill of a background.
	**/
	public abstract static class BackgroundFill extends Object {

		/**
		 * Default class constructor.
		**/
		public BackgroundFill() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes the type of a background.
	**/
	public abstract static class BackgroundType extends Object {

		/**
		 * Default class constructor.
		**/
		public BackgroundType() {}

	}

	/**
	 * This class is an abstract base class.
	 * Represents the scope to which bot commands are relevant.
	**/
	public abstract static class BotCommandScope extends Object {

		/**
		 * Default class constructor.
		**/
		public BotCommandScope() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes the reason why a call was discarded.
	**/
	public abstract static class CallDiscardReason extends Object {

		/**
		 * Default class constructor.
		**/
		public CallDiscardReason() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes the exact type of a problem with a call.
	**/
	public abstract static class CallProblem extends Object {

		/**
		 * Default class constructor.
		**/
		public CallProblem() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes the type of a call server.
	**/
	public abstract static class CallServerType extends Object {

		/**
		 * Default class constructor.
		**/
		public CallServerType() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes the current call state.
	**/
	public abstract static class CallState extends Object {

		/**
		 * Default class constructor.
		**/
		public CallState() {}

	}

	/**
	 * This class is an abstract base class.
	 * Represents a payload of a callback query.
	**/
	public abstract static class CallbackQueryPayload extends Object {

		/**
		 * Default class constructor.
		**/
		public CallbackQueryPayload() {}

	}

	/**
	 * This class is an abstract base class.
	 * Represents result of checking whether the current session can be used
	 * to transfer a chat ownership to another user.
	**/
	public abstract static class CanTransferOwnershipResult extends Object {

		/**
		 * Default class constructor.
		**/
		public CanTransferOwnershipResult() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes the different types of activity in a chat.
	**/
	public abstract static class ChatAction extends Object {

		/**
		 * Default class constructor.
		**/
		public ChatAction() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes actions which must be possible to do through a chat action
	 * bar.
	**/
	public abstract static class ChatActionBar extends Object {

		/**
		 * Default class constructor.
		**/
		public ChatActionBar() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes reactions available in the chat.
	**/
	public abstract static class ChatAvailableReactions extends Object {

		/**
		 * Default class constructor.
		**/
		public ChatAvailableReactions() {}

	}

	/**
	 * This class is an abstract base class.
	 * Represents a chat event.
	**/
	public abstract static class ChatEventAction extends Object {

		/**
		 * Default class constructor.
		**/
		public ChatEventAction() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes a list of chats.
	**/
	public abstract static class ChatList extends Object {

		/**
		 * Default class constructor.
		**/
		public ChatList() {}

	}

	/**
	 * This class is an abstract base class.
	 * Provides information about the status of a member in a chat.
	**/
	public abstract static class ChatMemberStatus extends Object {

		/**
		 * Default class constructor.
		**/
		public ChatMemberStatus() {}

	}

	/**
	 * This class is an abstract base class.
	 * Specifies the kind of chat members to return in searchChatMembers.
	**/
	public abstract static class ChatMembersFilter extends Object {

		/**
		 * Default class constructor.
		**/
		public ChatMembersFilter() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes type of a sticker, which was used to create a chat photo.
	**/
	public abstract static class ChatPhotoStickerType extends Object {

		/**
		 * Default class constructor.
		**/
		public ChatPhotoStickerType() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes the reason why a chat is reported.
	**/
	public abstract static class ChatReportReason extends Object {

		/**
		 * Default class constructor.
		**/
		public ChatReportReason() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes a reason why an external chat is shown in a chat list.
	**/
	public abstract static class ChatSource extends Object {

		/**
		 * Default class constructor.
		**/
		public ChatSource() {}

	}

	/**
	 * This class is an abstract base class.
	 * Contains a detailed statistics about a chat.
	**/
	public abstract static class ChatStatistics extends Object {

		/**
		 * Default class constructor.
		**/
		public ChatStatistics() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes the type of a chat.
	**/
	public abstract static class ChatType extends Object {

		/**
		 * Default class constructor.
		**/
		public ChatType() {}

	}

	/**
	 * This class is an abstract base class.
	 * Represents result of checking whether a username can be set for a
	 * chat.
	**/
	public abstract static class CheckChatUsernameResult extends Object {

		/**
		 * Default class constructor.
		**/
		public CheckChatUsernameResult() {}

	}

	/**
	 * This class is an abstract base class.
	 * Represents result of checking whether a name can be used for a new
	 * sticker set.
	**/
	public abstract static class CheckStickerSetNameResult extends Object {

		/**
		 * Default class constructor.
		**/
		public CheckStickerSetNameResult() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes the current state of the connection to Telegram servers.
	**/
	public abstract static class ConnectionState extends Object {

		/**
		 * Default class constructor.
		**/
		public ConnectionState() {}

	}

	/**
	 * This class is an abstract base class.
	 * Represents a data needed to subscribe for push notifications through
	 * registerDevice method. To use specific push notification service, the
	 * correct application platform must be specified and a valid server
	 * authentication data must be uploaded at https://my.telegram.org.
	**/
	public abstract static class DeviceToken extends Object {

		/**
		 * Default class constructor.
		**/
		public DeviceToken() {}

	}

	/**
	 * This class is an abstract base class.
	 * Contains animated stickers which must be used for dice animation
	 * rendering.
	**/
	public abstract static class DiceStickers extends Object {

		/**
		 * Default class constructor.
		**/
		public DiceStickers() {}

	}

	/**
	 * This class is an abstract base class.
	 * Contains authentication data for a email address.
	**/
	public abstract static class EmailAddressAuthentication extends Object {

		/**
		 * Default class constructor.
		**/
		public EmailAddressAuthentication() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes reset state of a email address.
	**/
	public abstract static class EmailAddressResetState extends Object {

		/**
		 * Default class constructor.
		**/
		public EmailAddressResetState() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes type of an emoji category.
	**/
	public abstract static class EmojiCategoryType extends Object {

		/**
		 * Default class constructor.
		**/
		public EmojiCategoryType() {}

	}

	/**
	 * This class is an abstract base class.
	 * Represents the type of a file.
	**/
	public abstract static class FileType extends Object {

		/**
		 * Default class constructor.
		**/
		public FileType() {}

	}

	/**
	 * This class is an abstract base class.
	 * Contains settings for Firebase Authentication in the official
	 * applications.
	**/
	public abstract static class FirebaseAuthenticationSettings extends Object {

		/**
		 * Default class constructor.
		**/
		public FirebaseAuthenticationSettings() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes the quality of a group call video.
	**/
	public abstract static class GroupCallVideoQuality extends Object {

		/**
		 * Default class constructor.
		**/
		public GroupCallVideoQuality() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes the type of an inline keyboard button.
	**/
	public abstract static class InlineKeyboardButtonType extends Object {

		/**
		 * Default class constructor.
		**/
		public InlineKeyboardButtonType() {}

	}

	/**
	 * This class is an abstract base class.
	 * Represents a single result of an inline query.
	**/
	public abstract static class InlineQueryResult extends Object {

		/**
		 * Default class constructor.
		**/
		public InlineQueryResult() {}

	}

	/**
	 * This class is an abstract base class.
	 * Represents a type of a button in results of inline query.
	**/
	public abstract static class InlineQueryResultsButtonType extends Object {

		/**
		 * Default class constructor.
		**/
		public InlineQueryResultsButtonType() {}

	}

	/**
	 * This class is an abstract base class.
	 * Contains information about background to set.
	**/
	public abstract static class InputBackground extends Object {

		/**
		 * Default class constructor.
		**/
		public InputBackground() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes a photo to be set as a user profile or chat photo.
	**/
	public abstract static class InputChatPhoto extends Object {

		/**
		 * Default class constructor.
		**/
		public InputChatPhoto() {}

	}

	/**
	 * This class is an abstract base class.
	 * Contains information about the payment method chosen by the user.
	**/
	public abstract static class InputCredentials extends Object {

		/**
		 * Default class constructor.
		**/
		public InputCredentials() {}

	}

	/**
	 * This class is an abstract base class.
	 * Points to a file.
	**/
	public abstract static class InputFile extends Object {

		/**
		 * Default class constructor.
		**/
		public InputFile() {}

	}

	/**
	 * This class is an abstract base class.
	 * Represents a single result of an inline query; for bots only.
	**/
	public abstract static class InputInlineQueryResult extends Object {

		/**
		 * Default class constructor.
		**/
		public InputInlineQueryResult() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes an invoice to process.
	**/
	public abstract static class InputInvoice extends Object {

		/**
		 * Default class constructor.
		**/
		public InputInvoice() {}

	}

	/**
	 * This class is an abstract base class.
	 * The content of a message to send.
	**/
	public abstract static class InputMessageContent extends Object {

		/**
		 * Default class constructor.
		**/
		public InputMessageContent() {}

	}

	/**
	 * This class is an abstract base class.
	 * Contains information about a Telegram Passport element to be saved.
	**/
	public abstract static class InputPassportElement extends Object {

		/**
		 * Default class constructor.
		**/
		public InputPassportElement() {}

	}

	/**
	 * This class is an abstract base class.
	 * Contains the description of an error in a Telegram Passport element;
	 * for bots only.
	**/
	public abstract static class InputPassportElementErrorSource extends Object {

		/**
		 * Default class constructor.
		**/
		public InputPassportElementErrorSource() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes an internal https://t.me or tg: link, which must be
	 * processed by the application in a special way.
	**/
	public abstract static class InternalLinkType extends Object {

		/**
		 * Default class constructor.
		**/
		public InternalLinkType() {}

	}

	/**
	 * This class is an abstract base class.
	 * Represents a JSON value.
	**/
	public abstract static class JsonValue extends Object {

		/**
		 * Default class constructor.
		**/
		public JsonValue() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes a keyboard button type.
	**/
	public abstract static class KeyboardButtonType extends Object {

		/**
		 * Default class constructor.
		**/
		public KeyboardButtonType() {}

	}

	/**
	 * This class is an abstract base class.
	 * Represents the value of a string in a language pack.
	**/
	public abstract static class LanguagePackStringValue extends Object {

		/**
		 * Default class constructor.
		**/
		public LanguagePackStringValue() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes a stream to which TDLib internal log is written.
	**/
	public abstract static class LogStream extends Object {

		/**
		 * Default class constructor.
		**/
		public LogStream() {}

	}

	/**
	 * This class is an abstract base class.
	 * Contains information about an inline button of type
	 * inlineKeyboardButtonTypeLoginUrl.
	**/
	public abstract static class LoginUrlInfo extends Object {

		/**
		 * Default class constructor.
		**/
		public LoginUrlInfo() {}

	}

	/**
	 * This class is an abstract base class.
	 * Part of the face, relative to which a mask is placed.
	**/
	public abstract static class MaskPoint extends Object {

		/**
		 * Default class constructor.
		**/
		public MaskPoint() {}

	}

	/**
	 * This class is an abstract base class.
	 * Contains the content of a message.
	**/
	public abstract static class MessageContent extends Object {

		/**
		 * Default class constructor.
		**/
		public MessageContent() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes a media, which is attached to an invoice.
	**/
	public abstract static class MessageExtendedMedia extends Object {

		/**
		 * Default class constructor.
		**/
		public MessageExtendedMedia() {}

	}

	/**
	 * This class is an abstract base class.
	 * Contains information about a file with messages exported from another
	 * app.
	**/
	public abstract static class MessageFileType extends Object {

		/**
		 * Default class constructor.
		**/
		public MessageFileType() {}

	}

	/**
	 * This class is an abstract base class.
	 * Contains information about the origin of a forwarded message.
	**/
	public abstract static class MessageForwardOrigin extends Object {

		/**
		 * Default class constructor.
		**/
		public MessageForwardOrigin() {}

	}

	/**
	 * This class is an abstract base class.
	 * Contains information about the time when a scheduled message will be
	 * sent.
	**/
	public abstract static class MessageSchedulingState extends Object {

		/**
		 * Default class constructor.
		**/
		public MessageSchedulingState() {}

	}

	/**
	 * This class is an abstract base class.
	 * Contains information about the sender of a message.
	**/
	public abstract static class MessageSender extends Object {

		/**
		 * Default class constructor.
		**/
		public MessageSender() {}

	}

	/**
	 * This class is an abstract base class.
	 * Contains information about the sending state of the message.
	**/
	public abstract static class MessageSendingState extends Object {

		/**
		 * Default class constructor.
		**/
		public MessageSendingState() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes source of a message.
	**/
	public abstract static class MessageSource extends Object {

		/**
		 * Default class constructor.
		**/
		public MessageSource() {}

	}

	/**
	 * This class is an abstract base class.
	 * Contains statistics about network usage.
	**/
	public abstract static class NetworkStatisticsEntry extends Object {

		/**
		 * Default class constructor.
		**/
		public NetworkStatisticsEntry() {}

	}

	/**
	 * This class is an abstract base class.
	 * Represents the type of a network.
	**/
	public abstract static class NetworkType extends Object {

		/**
		 * Default class constructor.
		**/
		public NetworkType() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes the type of notifications in a notification group.
	**/
	public abstract static class NotificationGroupType extends Object {

		/**
		 * Default class constructor.
		**/
		public NotificationGroupType() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes the types of chats to which notification settings are
	 * relevant.
	**/
	public abstract static class NotificationSettingsScope extends Object {

		/**
		 * Default class constructor.
		**/
		public NotificationSettingsScope() {}

	}

	/**
	 * This class is an abstract base class.
	 * Contains detailed information about a notification.
	**/
	public abstract static class NotificationType extends Object {

		/**
		 * Default class constructor.
		**/
		public NotificationType() {}

	}

	/**
	 * This class is an abstract base class.
	 * Represents the value of an option.
	**/
	public abstract static class OptionValue extends Object {

		/**
		 * Default class constructor.
		**/
		public OptionValue() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes a block of an instant view web page.
	**/
	public abstract static class PageBlock extends Object {

		/**
		 * Default class constructor.
		**/
		public PageBlock() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes a horizontal alignment of a table cell content.
	**/
	public abstract static class PageBlockHorizontalAlignment extends Object {

		/**
		 * Default class constructor.
		**/
		public PageBlockHorizontalAlignment() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes a Vertical alignment of a table cell content.
	**/
	public abstract static class PageBlockVerticalAlignment extends Object {

		/**
		 * Default class constructor.
		**/
		public PageBlockVerticalAlignment() {}

	}

	/**
	 * This class is an abstract base class.
	 * Contains information about a Telegram Passport element.
	**/
	public abstract static class PassportElement extends Object {

		/**
		 * Default class constructor.
		**/
		public PassportElement() {}

	}

	/**
	 * This class is an abstract base class.
	 * Contains the description of an error in a Telegram Passport element.
	**/
	public abstract static class PassportElementErrorSource extends Object {

		/**
		 * Default class constructor.
		**/
		public PassportElementErrorSource() {}

	}

	/**
	 * This class is an abstract base class.
	 * Contains the type of a Telegram Passport element.
	**/
	public abstract static class PassportElementType extends Object {

		/**
		 * Default class constructor.
		**/
		public PassportElementType() {}

	}

	/**
	 * This class is an abstract base class.
	 * Contains information about a payment provider.
	**/
	public abstract static class PaymentProvider extends Object {

		/**
		 * Default class constructor.
		**/
		public PaymentProvider() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes the type of a poll.
	**/
	public abstract static class PollType extends Object {

		/**
		 * Default class constructor.
		**/
		public PollType() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes a feature available to Premium users.
	**/
	public abstract static class PremiumFeature extends Object {

		/**
		 * Default class constructor.
		**/
		public PremiumFeature() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes type of a limit, increased for Premium users.
	**/
	public abstract static class PremiumLimitType extends Object {

		/**
		 * Default class constructor.
		**/
		public PremiumLimitType() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes a source from which the Premium features screen is opened.
	**/
	public abstract static class PremiumSource extends Object {

		/**
		 * Default class constructor.
		**/
		public PremiumSource() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes the type of a proxy server.
	**/
	public abstract static class ProxyType extends Object {

		/**
		 * Default class constructor.
		**/
		public ProxyType() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes a type of public chats.
	**/
	public abstract static class PublicChatType extends Object {

		/**
		 * Default class constructor.
		**/
		public PublicChatType() {}

	}

	/**
	 * This class is an abstract base class.
	 * Contains content of a push message notification.
	**/
	public abstract static class PushMessageContent extends Object {

		/**
		 * Default class constructor.
		**/
		public PushMessageContent() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes type of message reaction.
	**/
	public abstract static class ReactionType extends Object {

		/**
		 * Default class constructor.
		**/
		public ReactionType() {}

	}

	/**
	 * This class is an abstract base class.
	 * Contains a description of a custom keyboard and actions that can be
	 * done with it to quickly reply to bots.
	**/
	public abstract static class ReplyMarkup extends Object {

		/**
		 * Default class constructor.
		**/
		public ReplyMarkup() {}

	}

	/**
	 * This class is an abstract base class.
	 * Represents result of 2-step verification password reset.
	**/
	public abstract static class ResetPasswordResult extends Object {

		/**
		 * Default class constructor.
		**/
		public ResetPasswordResult() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes a text object inside an instant-view web page.
	**/
	public abstract static class RichText extends Object {

		/**
		 * Default class constructor.
		**/
		public RichText() {}

	}

	/**
	 * This class is an abstract base class.
	 * Represents a filter for message search results.
	**/
	public abstract static class SearchMessagesFilter extends Object {

		/**
		 * Default class constructor.
		**/
		public SearchMessagesFilter() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes the current secret chat state.
	**/
	public abstract static class SecretChatState extends Object {

		/**
		 * Default class constructor.
		**/
		public SecretChatState() {}

	}

	/**
	 * This class is an abstract base class.
	 * Represents the type of a session.
	**/
	public abstract static class SessionType extends Object {

		/**
		 * Default class constructor.
		**/
		public SessionType() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes result of speech recognition in a voice note.
	**/
	public abstract static class SpeechRecognitionResult extends Object {

		/**
		 * Default class constructor.
		**/
		public SpeechRecognitionResult() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes a statistical graph.
	**/
	public abstract static class StatisticalGraph extends Object {

		/**
		 * Default class constructor.
		**/
		public StatisticalGraph() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes format of a sticker.
	**/
	public abstract static class StickerFormat extends Object {

		/**
		 * Default class constructor.
		**/
		public StickerFormat() {}

	}

	/**
	 * This class is an abstract base class.
	 * Contains full information about sticker type.
	**/
	public abstract static class StickerFullType extends Object {

		/**
		 * Default class constructor.
		**/
		public StickerFullType() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes type of a sticker.
	**/
	public abstract static class StickerType extends Object {

		/**
		 * Default class constructor.
		**/
		public StickerType() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes a purpose of an in-store payment.
	**/
	public abstract static class StorePaymentPurpose extends Object {

		/**
		 * Default class constructor.
		**/
		public StorePaymentPurpose() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes an action suggested to the current user.
	**/
	public abstract static class SuggestedAction extends Object {

		/**
		 * Default class constructor.
		**/
		public SuggestedAction() {}

	}

	/**
	 * This class is an abstract base class.
	 * Specifies the kind of chat members to return in getSupergroupMembers.
	**/
	public abstract static class SupergroupMembersFilter extends Object {

		/**
		 * Default class constructor.
		**/
		public SupergroupMembersFilter() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes the type of a URL linking to an internal Telegram entity.
	**/
	public abstract static class TMeUrlType extends Object {

		/**
		 * Default class constructor.
		**/
		public TMeUrlType() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes the target chat to be opened.
	**/
	public abstract static class TargetChat extends Object {

		/**
		 * Default class constructor.
		**/
		public TargetChat() {}

	}

	/**
	 * This class is an abstract base class.
	 * Represents a part of the text which must be formatted differently.
	**/
	public abstract static class TextEntityType extends Object {

		/**
		 * Default class constructor.
		**/
		public TextEntityType() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes the way the text needs to be parsed for text entities.
	**/
	public abstract static class TextParseMode extends Object {

		/**
		 * Default class constructor.
		**/
		public TextParseMode() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes format of a thumbnail.
	**/
	public abstract static class ThumbnailFormat extends Object {

		/**
		 * Default class constructor.
		**/
		public ThumbnailFormat() {}

	}

	/**
	 * This class is an abstract base class.
	 * Represents the categories of chats for which a list of frequently
	 * used chats can be retrieved.
	**/
	public abstract static class TopChatCategory extends Object {

		/**
		 * Default class constructor.
		**/
		public TopChatCategory() {}

	}

	/**
	 * This class is an abstract base class.
	 * Contains notifications about data changes.
	**/
	public abstract static class Update extends Object {

		/**
		 * Default class constructor.
		**/
		public Update() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes available user privacy settings.
	**/
	public abstract static class UserPrivacySetting extends Object {

		/**
		 * Default class constructor.
		**/
		public UserPrivacySetting() {}

	}

	/**
	 * This class is an abstract base class.
	 * Represents a single rule for managing privacy settings.
	**/
	public abstract static class UserPrivacySettingRule extends Object {

		/**
		 * Default class constructor.
		**/
		public UserPrivacySettingRule() {}

	}

	/**
	 * This class is an abstract base class.
	 * Describes the last time the user was online.
	**/
	public abstract static class UserStatus extends Object {

		/**
		 * Default class constructor.
		**/
		public UserStatus() {}

	}

	/**
	 * This class is an abstract base class.
	 * Represents the type of a user. The following types are possible:
	 * regular users, deleted users and bots.
	**/
	public abstract static class UserType extends Object {

		/**
		 * Default class constructor.
		**/
		public UserType() {}

	}

	/**
	 * This class is an abstract base class.
	 * Represents a vector path command.
	**/
	public abstract static class VectorPathCommand extends Object {

		/**
		 * Default class constructor.
		**/
		public VectorPathCommand() {}

	}

	/**
	 * Access hash.
	**/
	public static final class AccessHash extends Object {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Access hash type.
		**/
		public AccessHashType type;

		/**
		 * Access hash.
		**/
		public long accessHash;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1984003302;

		/**
		 * Access hash.
		**/
		public AccessHash() {}

		/**
		 * Access hash.
		 *
		 * @param chatId Chat identifier.
		 * @param type Access hash type.
		 * @param accessHash Access hash.
		**/
		public AccessHash(long chatId, AccessHashType type, long accessHash) {
			this.chatId = chatId;
			this.type = type;
			this.accessHash = accessHash;
		}

		/**
		 * Access hash.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AccessHash(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case AccessHashTypeUser.CONSTRUCTOR: this.type = new AccessHashTypeUser(input); break;
					case AccessHashTypeChannel.CONSTRUCTOR: this.type = new AccessHashTypeChannel(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.accessHash = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AccessHash.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AccessHash.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.type == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.type.serialize(output);
			}
			output.writeLong(this.accessHash);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AccessHash accessHash = (AccessHash) o;
			if (this.chatId != accessHash.chatId) {
				return false;
			}
			if (!Objects.equals(this.type, accessHash.type)) {
				return false;
			}
			if (this.accessHash != accessHash.accessHash) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.type == null ? 0 : this.type.hashCode());
			return result;
		}
	}

	/**
	 * An access hash of an user.
	**/
	public static final class AccessHashTypeUser extends AccessHashType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 989783425;

		/**
		 * An access hash of an user.
		**/
		public AccessHashTypeUser() {}

		/**
		 * An access hash of an user.
		 *
		**/

		/**
		 * An access hash of an user.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AccessHashTypeUser(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AccessHashTypeUser.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AccessHashTypeUser.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return AccessHashTypeUser.CONSTRUCTOR;
		}
	}

	/**
	 * An access hash of a channel.
	**/
	public static final class AccessHashTypeChannel extends AccessHashType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 369077840;

		/**
		 * An access hash of a channel.
		**/
		public AccessHashTypeChannel() {}

		/**
		 * An access hash of a channel.
		 *
		**/

		/**
		 * An access hash of a channel.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AccessHashTypeChannel(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AccessHashTypeChannel.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AccessHashTypeChannel.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return AccessHashTypeChannel.CONSTRUCTOR;
		}
	}

	/**
	 * Contains information about the period of inactivity after which the
	 * current user&#039;s account will automatically be deleted.
	**/
	public static final class AccountTtl extends Object {


		/**
		 * Number of days of inactivity before the account will be flagged for deletion; 30-366 days.
		**/
		public int days;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1324495492;

		/**
		 * Contains information about the period of inactivity after which the current user&#039;s account will automatically be deleted.
		**/
		public AccountTtl() {}

		/**
		 * Contains information about the period of inactivity after which the current user&#039;s account will automatically be deleted.
		 *
		 * @param days Number of days of inactivity before the account will be flagged for deletion; 30-366 days.
		**/
		public AccountTtl(int days) {
			this.days = days;
		}

		/**
		 * Contains information about the period of inactivity after which the current user&#039;s account will automatically be deleted.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AccountTtl(DataInput input) throws IOException {
			this.days = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AccountTtl.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AccountTtl.CONSTRUCTOR);
			output.writeInt(this.days);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AccountTtl accountTtl = (AccountTtl) o;
			if (this.days != accountTtl.days) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.days);
		}
	}

	/**
	 * Represents a reaction applied to a message.
	**/
	public static final class AddedReaction extends Object {


		/**
		 * Type of the reaction.
		**/
		public ReactionType type;

		/**
		 * Identifier of the chat member, applied the reaction.
		**/
		public MessageSender senderId;

		/**
		 * Point in time (Unix timestamp) when the reaction was added.
		**/
		public int date;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1666271766;

		/**
		 * Represents a reaction applied to a message.
		**/
		public AddedReaction() {}

		/**
		 * Represents a reaction applied to a message.
		 *
		 * @param type Type of the reaction.
		 * @param senderId Identifier of the chat member, applied the reaction.
		 * @param date Point in time (Unix timestamp) when the reaction was added.
		**/
		public AddedReaction(ReactionType type, MessageSender senderId, int date) {
			this.type = type;
			this.senderId = senderId;
			this.date = date;
		}

		/**
		 * Represents a reaction applied to a message.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AddedReaction(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ReactionTypeEmoji.CONSTRUCTOR: this.type = new ReactionTypeEmoji(input); break;
					case ReactionTypeCustomEmoji.CONSTRUCTOR: this.type = new ReactionTypeCustomEmoji(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case MessageSenderUser.CONSTRUCTOR: this.senderId = new MessageSenderUser(input); break;
					case MessageSenderChat.CONSTRUCTOR: this.senderId = new MessageSenderChat(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.date = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AddedReaction.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AddedReaction.CONSTRUCTOR);
			if (this.type == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.type.serialize(output);
			}
			if (this.senderId == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.senderId.serialize(output);
			}
			output.writeInt(this.date);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AddedReaction addedReaction = (AddedReaction) o;
			if (!Objects.equals(this.type, addedReaction.type)) {
				return false;
			}
			if (!Objects.equals(this.senderId, addedReaction.senderId)) {
				return false;
			}
			if (this.date != addedReaction.date) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.date);
			result = result * 31 + (this.type == null ? 0 : this.type.hashCode());
			result = result * 31 + (this.senderId == null ? 0 : this.senderId.hashCode());
			return result;
		}
	}

	/**
	 * Represents a list of reactions added to a message.
	**/
	public static final class AddedReactions extends Object {


		/**
		 * The total number of found reactions.
		**/
		public int totalCount;

		/**
		 * The list of added reactions.
		**/
		public AddedReaction[] reactions;

		/**
		 * The offset for the next request. If empty, there are no more results.
		**/
		public String nextOffset;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 226352304;

		/**
		 * Represents a list of reactions added to a message.
		**/
		public AddedReactions() {}

		/**
		 * Represents a list of reactions added to a message.
		 *
		 * @param totalCount The total number of found reactions.
		 * @param reactions The list of added reactions.
		 * @param nextOffset The offset for the next request. If empty, there are no more results.
		**/
		public AddedReactions(int totalCount, AddedReaction[] reactions, String nextOffset) {
			this.totalCount = totalCount;
			this.reactions = reactions;
			this.nextOffset = nextOffset;
		}

		/**
		 * Represents a list of reactions added to a message.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AddedReactions(DataInput input) throws IOException {
			this.totalCount = input.readInt();
			if (input.readBoolean()) {
				this.reactions = new AddedReaction[input.readInt()];
				for (int i = 0; i < this.reactions.length; i++) {
					if (AddedReaction.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.reactions[i] = new AddedReaction(input);
				}
			}
			if (input.readBoolean()) {
				byte[] nextOffsetTmp = new byte[input.readInt()];
				input.readFully(nextOffsetTmp);
				this.nextOffset = new String(nextOffsetTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AddedReactions.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AddedReactions.CONSTRUCTOR);
			output.writeInt(this.totalCount);
			if (this.reactions == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.reactions.length);
				for (int i = 0; i < this.reactions.length; i++) {
					this.reactions[i].serialize(output);
				}
			}
			if (this.nextOffset == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nextOffsetTmp = this.nextOffset.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nextOffsetTmp.length);
				output.write(nextOffsetTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AddedReactions addedReactions = (AddedReactions) o;
			if (this.totalCount != addedReactions.totalCount) {
				return false;
			}
			if (!Arrays.equals(this.reactions, addedReactions.reactions)) {
				return false;
			}
			if (this.nextOffset != addedReactions.nextOffset) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.totalCount);
			result = result * 31 + (Arrays.hashCode(this.reactions));
			result = result * 31 + (this.nextOffset == null ? 0 : this.nextOffset.hashCode());
			return result;
		}
	}

	/**
	 * Describes an address.
	**/
	public static final class Address extends Object {


		/**
		 * A two-letter ISO 3166-1 alpha-2 country code.
		**/
		public String countryCode;

		/**
		 * State, if applicable.
		**/
		public String state;

		/**
		 * City.
		**/
		public String city;

		/**
		 * First line of the address.
		**/
		public String streetLine1;

		/**
		 * Second line of the address.
		**/
		public String streetLine2;

		/**
		 * Address postal code.
		**/
		public String postalCode;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2043654342;

		/**
		 * Describes an address.
		**/
		public Address() {}

		/**
		 * Describes an address.
		 *
		 * @param countryCode A two-letter ISO 3166-1 alpha-2 country code.
		 * @param state State, if applicable.
		 * @param city City.
		 * @param streetLine1 First line of the address.
		 * @param streetLine2 Second line of the address.
		 * @param postalCode Address postal code.
		**/
		public Address(String countryCode,
				String state,
				String city,
				String streetLine1,
				String streetLine2,
				String postalCode) {
			this.countryCode = countryCode;
			this.state = state;
			this.city = city;
			this.streetLine1 = streetLine1;
			this.streetLine2 = streetLine2;
			this.postalCode = postalCode;
		}

		/**
		 * Describes an address.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public Address(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] countryCodeTmp = new byte[input.readInt()];
				input.readFully(countryCodeTmp);
				this.countryCode = new String(countryCodeTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] stateTmp = new byte[input.readInt()];
				input.readFully(stateTmp);
				this.state = new String(stateTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] cityTmp = new byte[input.readInt()];
				input.readFully(cityTmp);
				this.city = new String(cityTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] streetLine1Tmp = new byte[input.readInt()];
				input.readFully(streetLine1Tmp);
				this.streetLine1 = new String(streetLine1Tmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] streetLine2Tmp = new byte[input.readInt()];
				input.readFully(streetLine2Tmp);
				this.streetLine2 = new String(streetLine2Tmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] postalCodeTmp = new byte[input.readInt()];
				input.readFully(postalCodeTmp);
				this.postalCode = new String(postalCodeTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return Address.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(Address.CONSTRUCTOR);
			if (this.countryCode == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] countryCodeTmp = this.countryCode.getBytes(StandardCharsets.UTF_8);
				output.writeInt(countryCodeTmp.length);
				output.write(countryCodeTmp);
			}
			if (this.state == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] stateTmp = this.state.getBytes(StandardCharsets.UTF_8);
				output.writeInt(stateTmp.length);
				output.write(stateTmp);
			}
			if (this.city == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] cityTmp = this.city.getBytes(StandardCharsets.UTF_8);
				output.writeInt(cityTmp.length);
				output.write(cityTmp);
			}
			if (this.streetLine1 == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] streetLine1Tmp = this.streetLine1.getBytes(StandardCharsets.UTF_8);
				output.writeInt(streetLine1Tmp.length);
				output.write(streetLine1Tmp);
			}
			if (this.streetLine2 == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] streetLine2Tmp = this.streetLine2.getBytes(StandardCharsets.UTF_8);
				output.writeInt(streetLine2Tmp.length);
				output.write(streetLine2Tmp);
			}
			if (this.postalCode == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] postalCodeTmp = this.postalCode.getBytes(StandardCharsets.UTF_8);
				output.writeInt(postalCodeTmp.length);
				output.write(postalCodeTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			Address address = (Address) o;
			if (this.countryCode != address.countryCode) {
				return false;
			}
			if (this.state != address.state) {
				return false;
			}
			if (this.city != address.city) {
				return false;
			}
			if (this.streetLine1 != address.streetLine1) {
				return false;
			}
			if (this.streetLine2 != address.streetLine2) {
				return false;
			}
			if (this.postalCode != address.postalCode) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.countryCode == null ? 0 : this.countryCode.hashCode();
			result = result * 31 + (this.state == null ? 0 : this.state.hashCode());
			result = result * 31 + (this.city == null ? 0 : this.city.hashCode());
			result = result * 31 + (this.streetLine1 == null ? 0 : this.streetLine1.hashCode());
			result = result * 31 + (this.streetLine2 == null ? 0 : this.streetLine2.hashCode());
			result = result * 31 + (this.postalCode == null ? 0 : this.postalCode.hashCode());
			return result;
		}
	}

	/**
	 * Animated variant of a chat photo in MPEG4 format.
	**/
	public static final class AnimatedChatPhoto extends Object {


		/**
		 * Animation width and height.
		**/
		public int length;

		/**
		 * Information about the animation file.
		**/
		public File file;

		/**
		 * Timestamp of the frame, used as a static chat photo.
		**/
		public double mainFrameTimestamp;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 191994926;

		/**
		 * Animated variant of a chat photo in MPEG4 format.
		**/
		public AnimatedChatPhoto() {}

		/**
		 * Animated variant of a chat photo in MPEG4 format.
		 *
		 * @param length Animation width and height.
		 * @param file Information about the animation file.
		 * @param mainFrameTimestamp Timestamp of the frame, used as a static chat photo.
		**/
		public AnimatedChatPhoto(int length, File file, double mainFrameTimestamp) {
			this.length = length;
			this.file = file;
			this.mainFrameTimestamp = mainFrameTimestamp;
		}

		/**
		 * Animated variant of a chat photo in MPEG4 format.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AnimatedChatPhoto(DataInput input) throws IOException {
			this.length = input.readInt();
			if (input.readBoolean()) {
				if (File.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.file = new File(input);
			}
			this.mainFrameTimestamp = input.readDouble();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AnimatedChatPhoto.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AnimatedChatPhoto.CONSTRUCTOR);
			output.writeInt(this.length);
			if (this.file == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.file.serialize(output);
			}
			output.writeDouble(this.mainFrameTimestamp);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AnimatedChatPhoto animatedChatPhoto = (AnimatedChatPhoto) o;
			if (this.length != animatedChatPhoto.length) {
				return false;
			}
			if (!Objects.equals(this.file, animatedChatPhoto.file)) {
				return false;
			}
			if (this.mainFrameTimestamp != animatedChatPhoto.mainFrameTimestamp) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.length);
			result = result * 31 + (this.file == null ? 0 : this.file.hashCode());
			return result;
		}
	}

	/**
	 * Describes an animated or custom representation of an emoji.
	**/
	public static final class AnimatedEmoji extends Object {


		/**
		 * Sticker for the emoji; may be null if yet unknown for a custom emoji. If the sticker is a custom emoji, it can have arbitrary format different from stickerFormatTgs.
		**/
		public Sticker sticker;

		/**
		 * Expected width of the sticker, which can be used if the sticker is null.
		**/
		public int stickerWidth;

		/**
		 * Expected height of the sticker, which can be used if the sticker is null.
		**/
		public int stickerHeight;

		/**
		 * Emoji modifier fitzpatrick type; 0-6; 0 if none.
		**/
		public int fitzpatrickType;

		/**
		 * File containing the sound to be played when the sticker is clicked; may be null. The sound is encoded with the Opus codec, and stored inside an OGG container.
		**/
		public File sound;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1378918079;

		/**
		 * Describes an animated or custom representation of an emoji.
		**/
		public AnimatedEmoji() {}

		/**
		 * Describes an animated or custom representation of an emoji.
		 *
		 * @param sticker Sticker for the emoji; may be null if yet unknown for a custom emoji. If the sticker is a custom emoji, it can have arbitrary format different from stickerFormatTgs.
		 * @param stickerWidth Expected width of the sticker, which can be used if the sticker is null.
		 * @param stickerHeight Expected height of the sticker, which can be used if the sticker is null.
		 * @param fitzpatrickType Emoji modifier fitzpatrick type; 0-6; 0 if none.
		 * @param sound File containing the sound to be played when the sticker is clicked; may be null. The sound is encoded with the Opus codec, and stored inside an OGG container.
		**/
		public AnimatedEmoji(Sticker sticker,
				int stickerWidth,
				int stickerHeight,
				int fitzpatrickType,
				File sound) {
			this.sticker = sticker;
			this.stickerWidth = stickerWidth;
			this.stickerHeight = stickerHeight;
			this.fitzpatrickType = fitzpatrickType;
			this.sound = sound;
		}

		/**
		 * Describes an animated or custom representation of an emoji.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AnimatedEmoji(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Sticker.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.sticker = new Sticker(input);
			}
			this.stickerWidth = input.readInt();
			this.stickerHeight = input.readInt();
			this.fitzpatrickType = input.readInt();
			if (input.readBoolean()) {
				if (File.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.sound = new File(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AnimatedEmoji.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AnimatedEmoji.CONSTRUCTOR);
			if (this.sticker == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.sticker.serialize(output);
			}
			output.writeInt(this.stickerWidth);
			output.writeInt(this.stickerHeight);
			output.writeInt(this.fitzpatrickType);
			if (this.sound == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.sound.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AnimatedEmoji animatedEmoji = (AnimatedEmoji) o;
			if (!Objects.equals(this.sticker, animatedEmoji.sticker)) {
				return false;
			}
			if (this.stickerWidth != animatedEmoji.stickerWidth) {
				return false;
			}
			if (this.stickerHeight != animatedEmoji.stickerHeight) {
				return false;
			}
			if (this.fitzpatrickType != animatedEmoji.fitzpatrickType) {
				return false;
			}
			if (!Objects.equals(this.sound, animatedEmoji.sound)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.stickerWidth);
			result = result * 31 + (this.sticker == null ? 0 : this.sticker.hashCode());
			result = result * 31 + (this.sound == null ? 0 : this.sound.hashCode());
			return result;
		}
	}

	/**
	 * Describes an animation file. The animation must be encoded in GIF or
	 * MPEG4 format.
	**/
	public static final class Animation extends Object {


		/**
		 * Duration of the animation, in seconds; as defined by the sender.
		**/
		public int duration;

		/**
		 * Width of the animation.
		**/
		public int width;

		/**
		 * Height of the animation.
		**/
		public int height;

		/**
		 * Original name of the file; as defined by the sender.
		**/
		public String fileName;

		/**
		 * MIME type of the file, usually &quot;image/gif&quot; or &quot;video/mp4&quot;.
		**/
		public String mimeType;

		/**
		 * True, if stickers were added to the animation. The list of corresponding sticker set can be received using getAttachedStickerSets.
		**/
		public boolean hasStickers;

		/**
		 * Animation minithumbnail; may be null.
		**/
		public Minithumbnail minithumbnail;

		/**
		 * Animation thumbnail in JPEG or MPEG4 format; may be null.
		**/
		public Thumbnail thumbnail;

		/**
		 * File containing the animation.
		**/
		public File animation;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -872359106;

		/**
		 * Describes an animation file. The animation must be encoded in GIF or MPEG4 format.
		**/
		public Animation() {}

		/**
		 * Describes an animation file. The animation must be encoded in GIF or MPEG4 format.
		 *
		 * @param duration Duration of the animation, in seconds; as defined by the sender.
		 * @param width Width of the animation.
		 * @param height Height of the animation.
		 * @param fileName Original name of the file; as defined by the sender.
		 * @param mimeType MIME type of the file, usually &quot;image/gif&quot; or &quot;video/mp4&quot;.
		 * @param hasStickers True, if stickers were added to the animation. The list of corresponding sticker set can be received using getAttachedStickerSets.
		 * @param minithumbnail Animation minithumbnail; may be null.
		 * @param thumbnail Animation thumbnail in JPEG or MPEG4 format; may be null.
		 * @param animation File containing the animation.
		**/
		public Animation(int duration,
				int width,
				int height,
				String fileName,
				String mimeType,
				boolean hasStickers,
				Minithumbnail minithumbnail,
				Thumbnail thumbnail,
				File animation) {
			this.duration = duration;
			this.width = width;
			this.height = height;
			this.fileName = fileName;
			this.mimeType = mimeType;
			this.hasStickers = hasStickers;
			this.minithumbnail = minithumbnail;
			this.thumbnail = thumbnail;
			this.animation = animation;
		}

		/**
		 * Describes an animation file. The animation must be encoded in GIF or MPEG4 format.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public Animation(DataInput input) throws IOException {
			this.duration = input.readInt();
			this.width = input.readInt();
			this.height = input.readInt();
			if (input.readBoolean()) {
				byte[] fileNameTmp = new byte[input.readInt()];
				input.readFully(fileNameTmp);
				this.fileName = new String(fileNameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] mimeTypeTmp = new byte[input.readInt()];
				input.readFully(mimeTypeTmp);
				this.mimeType = new String(mimeTypeTmp, StandardCharsets.UTF_8);
			}
			this.hasStickers = input.readBoolean();
			if (input.readBoolean()) {
				if (Minithumbnail.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.minithumbnail = new Minithumbnail(input);
			}
			if (input.readBoolean()) {
				if (Thumbnail.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.thumbnail = new Thumbnail(input);
			}
			if (input.readBoolean()) {
				if (File.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.animation = new File(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return Animation.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(Animation.CONSTRUCTOR);
			output.writeInt(this.duration);
			output.writeInt(this.width);
			output.writeInt(this.height);
			if (this.fileName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] fileNameTmp = this.fileName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(fileNameTmp.length);
				output.write(fileNameTmp);
			}
			if (this.mimeType == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] mimeTypeTmp = this.mimeType.getBytes(StandardCharsets.UTF_8);
				output.writeInt(mimeTypeTmp.length);
				output.write(mimeTypeTmp);
			}
			output.writeBoolean(this.hasStickers);
			if (this.minithumbnail == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.minithumbnail.serialize(output);
			}
			if (this.thumbnail == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.thumbnail.serialize(output);
			}
			if (this.animation == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.animation.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			Animation animation = (Animation) o;
			if (this.duration != animation.duration) {
				return false;
			}
			if (this.width != animation.width) {
				return false;
			}
			if (this.height != animation.height) {
				return false;
			}
			if (this.fileName != animation.fileName) {
				return false;
			}
			if (this.mimeType != animation.mimeType) {
				return false;
			}
			if (this.hasStickers != animation.hasStickers) {
				return false;
			}
			if (!Objects.equals(this.minithumbnail, animation.minithumbnail)) {
				return false;
			}
			if (!Objects.equals(this.thumbnail, animation.thumbnail)) {
				return false;
			}
			if (!Objects.equals(this.animation, animation.animation)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.duration);
			result = result * 31 + (this.fileName == null ? 0 : this.fileName.hashCode());
			result = result * 31 + (this.mimeType == null ? 0 : this.mimeType.hashCode());
			result = result * 31 + (this.minithumbnail == null ? 0 : this.minithumbnail.hashCode());
			result = result * 31 + (this.thumbnail == null ? 0 : this.thumbnail.hashCode());
			result = result * 31 + (this.animation == null ? 0 : this.animation.hashCode());
			return result;
		}
	}

	/**
	 * Represents a list of animations.
	**/
	public static final class Animations extends Object {


		/**
		 * List of animations.
		**/
		public Animation[] animations;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 344216945;

		/**
		 * Represents a list of animations.
		**/
		public Animations() {}

		/**
		 * Represents a list of animations.
		 *
		 * @param animations List of animations.
		**/
		public Animations(Animation[] animations) {
			this.animations = animations;
		}

		/**
		 * Represents a list of animations.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public Animations(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.animations = new Animation[input.readInt()];
				for (int i = 0; i < this.animations.length; i++) {
					if (Animation.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.animations[i] = new Animation(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return Animations.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(Animations.CONSTRUCTOR);
			if (this.animations == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.animations.length);
				for (int i = 0; i < this.animations.length; i++) {
					this.animations[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			Animations animations = (Animations) o;
			if (!Arrays.equals(this.animations, animations.animations)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.animations);
		}
	}

	/**
	 * Represents a bot, which can be added to attachment menu.
	**/
	public static final class AttachmentMenuBot extends Object {


		/**
		 * User identifier of the bot added to attachment menu.
		**/
		public long botUserId;

		/**
		 * True, if the bot supports opening from attachment menu in the chat with the bot.
		**/
		public boolean supportsSelfChat;

		/**
		 * True, if the bot supports opening from attachment menu in private chats with ordinary users.
		**/
		public boolean supportsUserChats;

		/**
		 * True, if the bot supports opening from attachment menu in private chats with other bots.
		**/
		public boolean supportsBotChats;

		/**
		 * True, if the bot supports opening from attachment menu in basic group and supergroup chats.
		**/
		public boolean supportsGroupChats;

		/**
		 * True, if the bot supports opening from attachment menu in channel chats.
		**/
		public boolean supportsChannelChats;

		/**
		 * True, if the bot supports &quot;settings_button_pressed&quot; event.
		**/
		public boolean supportsSettings;

		/**
		 * True, if the user must be asked for the permission to the bot to send them messages.
		**/
		public boolean requestWriteAccess;

		/**
		 * Name for the bot in attachment menu.
		**/
		public String name;

		/**
		 * Color to highlight selected name of the bot if appropriate; may be null.
		**/
		public AttachmentMenuBotColor nameColor;

		/**
		 * Default attachment menu icon for the bot in SVG format; may be null.
		**/
		public File defaultIcon;

		/**
		 * Attachment menu icon for the bot in SVG format for the official iOS app; may be null.
		**/
		public File iosStaticIcon;

		/**
		 * Attachment menu icon for the bot in TGS format for the official iOS app; may be null.
		**/
		public File iosAnimatedIcon;

		/**
		 * Attachment menu icon for the bot in TGS format for the official Android app; may be null.
		**/
		public File androidIcon;

		/**
		 * Attachment menu icon for the bot in TGS format for the official native macOS app; may be null.
		**/
		public File macosIcon;

		/**
		 * Color to highlight selected icon of the bot if appropriate; may be null.
		**/
		public AttachmentMenuBotColor iconColor;

		/**
		 * Default placeholder for opened Web Apps in SVG format; may be null.
		**/
		public File webAppPlaceholder;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1495310429;

		/**
		 * Represents a bot, which can be added to attachment menu.
		**/
		public AttachmentMenuBot() {}

		/**
		 * Represents a bot, which can be added to attachment menu.
		 *
		 * @param botUserId User identifier of the bot added to attachment menu.
		 * @param supportsSelfChat True, if the bot supports opening from attachment menu in the chat with the bot.
		 * @param supportsUserChats True, if the bot supports opening from attachment menu in private chats with ordinary users.
		 * @param supportsBotChats True, if the bot supports opening from attachment menu in private chats with other bots.
		 * @param supportsGroupChats True, if the bot supports opening from attachment menu in basic group and supergroup chats.
		 * @param supportsChannelChats True, if the bot supports opening from attachment menu in channel chats.
		 * @param supportsSettings True, if the bot supports &quot;settings_button_pressed&quot; event.
		 * @param requestWriteAccess True, if the user must be asked for the permission to the bot to send them messages.
		 * @param name Name for the bot in attachment menu.
		 * @param nameColor Color to highlight selected name of the bot if appropriate; may be null.
		 * @param defaultIcon Default attachment menu icon for the bot in SVG format; may be null.
		 * @param iosStaticIcon Attachment menu icon for the bot in SVG format for the official iOS app; may be null.
		 * @param iosAnimatedIcon Attachment menu icon for the bot in TGS format for the official iOS app; may be null.
		 * @param androidIcon Attachment menu icon for the bot in TGS format for the official Android app; may be null.
		 * @param macosIcon Attachment menu icon for the bot in TGS format for the official native macOS app; may be null.
		 * @param iconColor Color to highlight selected icon of the bot if appropriate; may be null.
		 * @param webAppPlaceholder Default placeholder for opened Web Apps in SVG format; may be null.
		**/
		public AttachmentMenuBot(long botUserId,
				boolean supportsSelfChat,
				boolean supportsUserChats,
				boolean supportsBotChats,
				boolean supportsGroupChats,
				boolean supportsChannelChats,
				boolean supportsSettings,
				boolean requestWriteAccess,
				String name,
				AttachmentMenuBotColor nameColor,
				File defaultIcon,
				File iosStaticIcon,
				File iosAnimatedIcon,
				File androidIcon,
				File macosIcon,
				AttachmentMenuBotColor iconColor,
				File webAppPlaceholder) {
			this.botUserId = botUserId;
			this.supportsSelfChat = supportsSelfChat;
			this.supportsUserChats = supportsUserChats;
			this.supportsBotChats = supportsBotChats;
			this.supportsGroupChats = supportsGroupChats;
			this.supportsChannelChats = supportsChannelChats;
			this.supportsSettings = supportsSettings;
			this.requestWriteAccess = requestWriteAccess;
			this.name = name;
			this.nameColor = nameColor;
			this.defaultIcon = defaultIcon;
			this.iosStaticIcon = iosStaticIcon;
			this.iosAnimatedIcon = iosAnimatedIcon;
			this.androidIcon = androidIcon;
			this.macosIcon = macosIcon;
			this.iconColor = iconColor;
			this.webAppPlaceholder = webAppPlaceholder;
		}

		/**
		 * Represents a bot, which can be added to attachment menu.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AttachmentMenuBot(DataInput input) throws IOException {
			this.botUserId = input.readLong();
			this.supportsSelfChat = input.readBoolean();
			this.supportsUserChats = input.readBoolean();
			this.supportsBotChats = input.readBoolean();
			this.supportsGroupChats = input.readBoolean();
			this.supportsChannelChats = input.readBoolean();
			this.supportsSettings = input.readBoolean();
			this.requestWriteAccess = input.readBoolean();
			if (input.readBoolean()) {
				byte[] nameTmp = new byte[input.readInt()];
				input.readFully(nameTmp);
				this.name = new String(nameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (AttachmentMenuBotColor.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.nameColor = new AttachmentMenuBotColor(input);
			}
			if (input.readBoolean()) {
				if (File.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.defaultIcon = new File(input);
			}
			if (input.readBoolean()) {
				if (File.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.iosStaticIcon = new File(input);
			}
			if (input.readBoolean()) {
				if (File.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.iosAnimatedIcon = new File(input);
			}
			if (input.readBoolean()) {
				if (File.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.androidIcon = new File(input);
			}
			if (input.readBoolean()) {
				if (File.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.macosIcon = new File(input);
			}
			if (input.readBoolean()) {
				if (AttachmentMenuBotColor.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.iconColor = new AttachmentMenuBotColor(input);
			}
			if (input.readBoolean()) {
				if (File.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.webAppPlaceholder = new File(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AttachmentMenuBot.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AttachmentMenuBot.CONSTRUCTOR);
			output.writeLong(this.botUserId);
			output.writeBoolean(this.supportsSelfChat);
			output.writeBoolean(this.supportsUserChats);
			output.writeBoolean(this.supportsBotChats);
			output.writeBoolean(this.supportsGroupChats);
			output.writeBoolean(this.supportsChannelChats);
			output.writeBoolean(this.supportsSettings);
			output.writeBoolean(this.requestWriteAccess);
			if (this.name == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nameTmp = this.name.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nameTmp.length);
				output.write(nameTmp);
			}
			if (this.nameColor == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.nameColor.serialize(output);
			}
			if (this.defaultIcon == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.defaultIcon.serialize(output);
			}
			if (this.iosStaticIcon == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.iosStaticIcon.serialize(output);
			}
			if (this.iosAnimatedIcon == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.iosAnimatedIcon.serialize(output);
			}
			if (this.androidIcon == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.androidIcon.serialize(output);
			}
			if (this.macosIcon == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.macosIcon.serialize(output);
			}
			if (this.iconColor == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.iconColor.serialize(output);
			}
			if (this.webAppPlaceholder == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.webAppPlaceholder.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AttachmentMenuBot attachmentMenuBot = (AttachmentMenuBot) o;
			if (this.botUserId != attachmentMenuBot.botUserId) {
				return false;
			}
			if (this.supportsSelfChat != attachmentMenuBot.supportsSelfChat) {
				return false;
			}
			if (this.supportsUserChats != attachmentMenuBot.supportsUserChats) {
				return false;
			}
			if (this.supportsBotChats != attachmentMenuBot.supportsBotChats) {
				return false;
			}
			if (this.supportsGroupChats != attachmentMenuBot.supportsGroupChats) {
				return false;
			}
			if (this.supportsChannelChats != attachmentMenuBot.supportsChannelChats) {
				return false;
			}
			if (this.supportsSettings != attachmentMenuBot.supportsSettings) {
				return false;
			}
			if (this.requestWriteAccess != attachmentMenuBot.requestWriteAccess) {
				return false;
			}
			if (this.name != attachmentMenuBot.name) {
				return false;
			}
			if (!Objects.equals(this.nameColor, attachmentMenuBot.nameColor)) {
				return false;
			}
			if (!Objects.equals(this.defaultIcon, attachmentMenuBot.defaultIcon)) {
				return false;
			}
			if (!Objects.equals(this.iosStaticIcon, attachmentMenuBot.iosStaticIcon)) {
				return false;
			}
			if (!Objects.equals(this.iosAnimatedIcon, attachmentMenuBot.iosAnimatedIcon)) {
				return false;
			}
			if (!Objects.equals(this.androidIcon, attachmentMenuBot.androidIcon)) {
				return false;
			}
			if (!Objects.equals(this.macosIcon, attachmentMenuBot.macosIcon)) {
				return false;
			}
			if (!Objects.equals(this.iconColor, attachmentMenuBot.iconColor)) {
				return false;
			}
			if (!Objects.equals(this.webAppPlaceholder, attachmentMenuBot.webAppPlaceholder)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.botUserId);
			result = result * 31 + (this.name == null ? 0 : this.name.hashCode());
			result = result * 31 + (this.nameColor == null ? 0 : this.nameColor.hashCode());
			result = result * 31 + (this.defaultIcon == null ? 0 : this.defaultIcon.hashCode());
			result = result * 31 + (this.iosStaticIcon == null ? 0 : this.iosStaticIcon.hashCode());
			result = result * 31 + (this.iosAnimatedIcon == null ? 0 : this.iosAnimatedIcon.hashCode());
			result = result * 31 + (this.androidIcon == null ? 0 : this.androidIcon.hashCode());
			result = result * 31 + (this.macosIcon == null ? 0 : this.macosIcon.hashCode());
			result = result * 31 + (this.iconColor == null ? 0 : this.iconColor.hashCode());
			result = result * 31 + (this.webAppPlaceholder == null ? 0 : this.webAppPlaceholder.hashCode());
			return result;
		}
	}

	/**
	 * Describes a color to highlight a bot added to attachment menu.
	**/
	public static final class AttachmentMenuBotColor extends Object {


		/**
		 * Color in the RGB24 format for light themes.
		**/
		public int lightColor;

		/**
		 * Color in the RGB24 format for dark themes.
		**/
		public int darkColor;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1680039612;

		/**
		 * Describes a color to highlight a bot added to attachment menu.
		**/
		public AttachmentMenuBotColor() {}

		/**
		 * Describes a color to highlight a bot added to attachment menu.
		 *
		 * @param lightColor Color in the RGB24 format for light themes.
		 * @param darkColor Color in the RGB24 format for dark themes.
		**/
		public AttachmentMenuBotColor(int lightColor, int darkColor) {
			this.lightColor = lightColor;
			this.darkColor = darkColor;
		}

		/**
		 * Describes a color to highlight a bot added to attachment menu.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AttachmentMenuBotColor(DataInput input) throws IOException {
			this.lightColor = input.readInt();
			this.darkColor = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AttachmentMenuBotColor.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AttachmentMenuBotColor.CONSTRUCTOR);
			output.writeInt(this.lightColor);
			output.writeInt(this.darkColor);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AttachmentMenuBotColor attachmentMenuBotColor = (AttachmentMenuBotColor) o;
			if (this.lightColor != attachmentMenuBotColor.lightColor) {
				return false;
			}
			if (this.darkColor != attachmentMenuBotColor.darkColor) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.lightColor);
			return result;
		}
	}

	/**
	 * Describes an audio file. Audio is usually in MP3 or M4A format.
	**/
	public static final class Audio extends Object {


		/**
		 * Duration of the audio, in seconds; as defined by the sender.
		**/
		public int duration;

		/**
		 * Title of the audio; as defined by the sender.
		**/
		public String title;

		/**
		 * Performer of the audio; as defined by the sender.
		**/
		public String performer;

		/**
		 * Original name of the file; as defined by the sender.
		**/
		public String fileName;

		/**
		 * The MIME type of the file; as defined by the sender.
		**/
		public String mimeType;

		/**
		 * The minithumbnail of the album cover; may be null.
		**/
		public Minithumbnail albumCoverMinithumbnail;

		/**
		 * The thumbnail of the album cover in JPEG format; as defined by the sender. The full size thumbnail is supposed to be extracted from the downloaded audio file; may be null.
		**/
		public Thumbnail albumCoverThumbnail;

		/**
		 * Album cover variants to use if the downloaded audio file contains no album cover. Provided thumbnail dimensions are approximate.
		**/
		public Thumbnail[] externalAlbumCovers;

		/**
		 * File containing the audio.
		**/
		public File audio;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -166398841;

		/**
		 * Describes an audio file. Audio is usually in MP3 or M4A format.
		**/
		public Audio() {}

		/**
		 * Describes an audio file. Audio is usually in MP3 or M4A format.
		 *
		 * @param duration Duration of the audio, in seconds; as defined by the sender.
		 * @param title Title of the audio; as defined by the sender.
		 * @param performer Performer of the audio; as defined by the sender.
		 * @param fileName Original name of the file; as defined by the sender.
		 * @param mimeType The MIME type of the file; as defined by the sender.
		 * @param albumCoverMinithumbnail The minithumbnail of the album cover; may be null.
		 * @param albumCoverThumbnail The thumbnail of the album cover in JPEG format; as defined by the sender. The full size thumbnail is supposed to be extracted from the downloaded audio file; may be null.
		 * @param externalAlbumCovers Album cover variants to use if the downloaded audio file contains no album cover. Provided thumbnail dimensions are approximate.
		 * @param audio File containing the audio.
		**/
		public Audio(int duration,
				String title,
				String performer,
				String fileName,
				String mimeType,
				Minithumbnail albumCoverMinithumbnail,
				Thumbnail albumCoverThumbnail,
				Thumbnail[] externalAlbumCovers,
				File audio) {
			this.duration = duration;
			this.title = title;
			this.performer = performer;
			this.fileName = fileName;
			this.mimeType = mimeType;
			this.albumCoverMinithumbnail = albumCoverMinithumbnail;
			this.albumCoverThumbnail = albumCoverThumbnail;
			this.externalAlbumCovers = externalAlbumCovers;
			this.audio = audio;
		}

		/**
		 * Describes an audio file. Audio is usually in MP3 or M4A format.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public Audio(DataInput input) throws IOException {
			this.duration = input.readInt();
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] performerTmp = new byte[input.readInt()];
				input.readFully(performerTmp);
				this.performer = new String(performerTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] fileNameTmp = new byte[input.readInt()];
				input.readFully(fileNameTmp);
				this.fileName = new String(fileNameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] mimeTypeTmp = new byte[input.readInt()];
				input.readFully(mimeTypeTmp);
				this.mimeType = new String(mimeTypeTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (Minithumbnail.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.albumCoverMinithumbnail = new Minithumbnail(input);
			}
			if (input.readBoolean()) {
				if (Thumbnail.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.albumCoverThumbnail = new Thumbnail(input);
			}
			if (input.readBoolean()) {
				this.externalAlbumCovers = new Thumbnail[input.readInt()];
				for (int i = 0; i < this.externalAlbumCovers.length; i++) {
					if (Thumbnail.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.externalAlbumCovers[i] = new Thumbnail(input);
				}
			}
			if (input.readBoolean()) {
				if (File.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.audio = new File(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return Audio.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(Audio.CONSTRUCTOR);
			output.writeInt(this.duration);
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
			if (this.performer == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] performerTmp = this.performer.getBytes(StandardCharsets.UTF_8);
				output.writeInt(performerTmp.length);
				output.write(performerTmp);
			}
			if (this.fileName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] fileNameTmp = this.fileName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(fileNameTmp.length);
				output.write(fileNameTmp);
			}
			if (this.mimeType == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] mimeTypeTmp = this.mimeType.getBytes(StandardCharsets.UTF_8);
				output.writeInt(mimeTypeTmp.length);
				output.write(mimeTypeTmp);
			}
			if (this.albumCoverMinithumbnail == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.albumCoverMinithumbnail.serialize(output);
			}
			if (this.albumCoverThumbnail == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.albumCoverThumbnail.serialize(output);
			}
			if (this.externalAlbumCovers == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.externalAlbumCovers.length);
				for (int i = 0; i < this.externalAlbumCovers.length; i++) {
					this.externalAlbumCovers[i].serialize(output);
				}
			}
			if (this.audio == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.audio.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			Audio audio = (Audio) o;
			if (this.duration != audio.duration) {
				return false;
			}
			if (this.title != audio.title) {
				return false;
			}
			if (this.performer != audio.performer) {
				return false;
			}
			if (this.fileName != audio.fileName) {
				return false;
			}
			if (this.mimeType != audio.mimeType) {
				return false;
			}
			if (!Objects.equals(this.albumCoverMinithumbnail, audio.albumCoverMinithumbnail)) {
				return false;
			}
			if (!Objects.equals(this.albumCoverThumbnail, audio.albumCoverThumbnail)) {
				return false;
			}
			if (!Arrays.equals(this.externalAlbumCovers, audio.externalAlbumCovers)) {
				return false;
			}
			if (!Objects.equals(this.audio, audio.audio)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.duration);
			result = result * 31 + (this.title == null ? 0 : this.title.hashCode());
			result = result * 31 + (this.performer == null ? 0 : this.performer.hashCode());
			result = result * 31 + (this.fileName == null ? 0 : this.fileName.hashCode());
			result = result * 31 + (this.mimeType == null ? 0 : this.mimeType.hashCode());
			result = result * 31 + (this.albumCoverMinithumbnail == null ? 0 : this.albumCoverMinithumbnail.hashCode());
			result = result * 31 + (this.albumCoverThumbnail == null ? 0 : this.albumCoverThumbnail.hashCode());
			result = result * 31 + (Arrays.hashCode(this.externalAlbumCovers));
			result = result * 31 + (this.audio == null ? 0 : this.audio.hashCode());
			return result;
		}
	}

	/**
	 * Information about the authentication code that was sent.
	**/
	public static final class AuthenticationCodeInfo extends Object {


		/**
		 * A phone number that is being authenticated.
		**/
		public String phoneNumber;

		/**
		 * The way the code was sent to the user.
		**/
		public AuthenticationCodeType type;

		/**
		 * The way the next code will be sent to the user; may be null.
		**/
		public AuthenticationCodeType nextType;

		/**
		 * Timeout before the code can be re-sent, in seconds.
		**/
		public int timeout;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -860345416;

		/**
		 * Information about the authentication code that was sent.
		**/
		public AuthenticationCodeInfo() {}

		/**
		 * Information about the authentication code that was sent.
		 *
		 * @param phoneNumber A phone number that is being authenticated.
		 * @param type The way the code was sent to the user.
		 * @param nextType The way the next code will be sent to the user; may be null.
		 * @param timeout Timeout before the code can be re-sent, in seconds.
		**/
		public AuthenticationCodeInfo(String phoneNumber,
				AuthenticationCodeType type,
				AuthenticationCodeType nextType,
				int timeout) {
			this.phoneNumber = phoneNumber;
			this.type = type;
			this.nextType = nextType;
			this.timeout = timeout;
		}

		/**
		 * Information about the authentication code that was sent.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AuthenticationCodeInfo(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] phoneNumberTmp = new byte[input.readInt()];
				input.readFully(phoneNumberTmp);
				this.phoneNumber = new String(phoneNumberTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case AuthenticationCodeTypeTelegramMessage.CONSTRUCTOR: this.type = new AuthenticationCodeTypeTelegramMessage(input); break;
					case AuthenticationCodeTypeSms.CONSTRUCTOR: this.type = new AuthenticationCodeTypeSms(input); break;
					case AuthenticationCodeTypeCall.CONSTRUCTOR: this.type = new AuthenticationCodeTypeCall(input); break;
					case AuthenticationCodeTypeFlashCall.CONSTRUCTOR: this.type = new AuthenticationCodeTypeFlashCall(input); break;
					case AuthenticationCodeTypeMissedCall.CONSTRUCTOR: this.type = new AuthenticationCodeTypeMissedCall(input); break;
					case AuthenticationCodeTypeFragment.CONSTRUCTOR: this.type = new AuthenticationCodeTypeFragment(input); break;
					case AuthenticationCodeTypeFirebaseAndroid.CONSTRUCTOR: this.type = new AuthenticationCodeTypeFirebaseAndroid(input); break;
					case AuthenticationCodeTypeFirebaseIos.CONSTRUCTOR: this.type = new AuthenticationCodeTypeFirebaseIos(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case AuthenticationCodeTypeTelegramMessage.CONSTRUCTOR: this.nextType = new AuthenticationCodeTypeTelegramMessage(input); break;
					case AuthenticationCodeTypeSms.CONSTRUCTOR: this.nextType = new AuthenticationCodeTypeSms(input); break;
					case AuthenticationCodeTypeCall.CONSTRUCTOR: this.nextType = new AuthenticationCodeTypeCall(input); break;
					case AuthenticationCodeTypeFlashCall.CONSTRUCTOR: this.nextType = new AuthenticationCodeTypeFlashCall(input); break;
					case AuthenticationCodeTypeMissedCall.CONSTRUCTOR: this.nextType = new AuthenticationCodeTypeMissedCall(input); break;
					case AuthenticationCodeTypeFragment.CONSTRUCTOR: this.nextType = new AuthenticationCodeTypeFragment(input); break;
					case AuthenticationCodeTypeFirebaseAndroid.CONSTRUCTOR: this.nextType = new AuthenticationCodeTypeFirebaseAndroid(input); break;
					case AuthenticationCodeTypeFirebaseIos.CONSTRUCTOR: this.nextType = new AuthenticationCodeTypeFirebaseIos(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.timeout = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AuthenticationCodeInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AuthenticationCodeInfo.CONSTRUCTOR);
			if (this.phoneNumber == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] phoneNumberTmp = this.phoneNumber.getBytes(StandardCharsets.UTF_8);
				output.writeInt(phoneNumberTmp.length);
				output.write(phoneNumberTmp);
			}
			if (this.type == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.type.serialize(output);
			}
			if (this.nextType == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.nextType.serialize(output);
			}
			output.writeInt(this.timeout);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AuthenticationCodeInfo authenticationCodeInfo = (AuthenticationCodeInfo) o;
			if (this.phoneNumber != authenticationCodeInfo.phoneNumber) {
				return false;
			}
			if (!Objects.equals(this.type, authenticationCodeInfo.type)) {
				return false;
			}
			if (!Objects.equals(this.nextType, authenticationCodeInfo.nextType)) {
				return false;
			}
			if (this.timeout != authenticationCodeInfo.timeout) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.timeout);
			result = result * 31 + (this.phoneNumber == null ? 0 : this.phoneNumber.hashCode());
			result = result * 31 + (this.type == null ? 0 : this.type.hashCode());
			result = result * 31 + (this.nextType == null ? 0 : this.nextType.hashCode());
			return result;
		}
	}

	/**
	 * An authentication code is delivered via a private Telegram message,
	 * which can be viewed from another active session.
	**/
	public static final class AuthenticationCodeTypeTelegramMessage extends AuthenticationCodeType {


		/**
		 * Length of the code.
		**/
		public int length;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2079628074;

		/**
		 * An authentication code is delivered via a private Telegram message, which can be viewed from another active session.
		**/
		public AuthenticationCodeTypeTelegramMessage() {}

		/**
		 * An authentication code is delivered via a private Telegram message, which can be viewed from another active session.
		 *
		 * @param length Length of the code.
		**/
		public AuthenticationCodeTypeTelegramMessage(int length) {
			this.length = length;
		}

		/**
		 * An authentication code is delivered via a private Telegram message, which can be viewed from another active session.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AuthenticationCodeTypeTelegramMessage(DataInput input) throws IOException {
			this.length = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AuthenticationCodeTypeTelegramMessage.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AuthenticationCodeTypeTelegramMessage.CONSTRUCTOR);
			output.writeInt(this.length);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AuthenticationCodeTypeTelegramMessage authenticationCodeTypeTelegramMessage = (AuthenticationCodeTypeTelegramMessage) o;
			if (this.length != authenticationCodeTypeTelegramMessage.length) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.length);
		}
	}

	/**
	 * An authentication code is delivered via an SMS message to the
	 * specified phone number; applications may not receive this type of
	 * code.
	**/
	public static final class AuthenticationCodeTypeSms extends AuthenticationCodeType {


		/**
		 * Length of the code.
		**/
		public int length;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 962650760;

		/**
		 * An authentication code is delivered via an SMS message to the specified phone number; applications may not receive this type of code.
		**/
		public AuthenticationCodeTypeSms() {}

		/**
		 * An authentication code is delivered via an SMS message to the specified phone number; applications may not receive this type of code.
		 *
		 * @param length Length of the code.
		**/
		public AuthenticationCodeTypeSms(int length) {
			this.length = length;
		}

		/**
		 * An authentication code is delivered via an SMS message to the specified phone number; applications may not receive this type of code.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AuthenticationCodeTypeSms(DataInput input) throws IOException {
			this.length = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AuthenticationCodeTypeSms.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AuthenticationCodeTypeSms.CONSTRUCTOR);
			output.writeInt(this.length);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AuthenticationCodeTypeSms authenticationCodeTypeSms = (AuthenticationCodeTypeSms) o;
			if (this.length != authenticationCodeTypeSms.length) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.length);
		}
	}

	/**
	 * An authentication code is delivered via a phone call to the specified
	 * phone number.
	**/
	public static final class AuthenticationCodeTypeCall extends AuthenticationCodeType {


		/**
		 * Length of the code.
		**/
		public int length;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1636265063;

		/**
		 * An authentication code is delivered via a phone call to the specified phone number.
		**/
		public AuthenticationCodeTypeCall() {}

		/**
		 * An authentication code is delivered via a phone call to the specified phone number.
		 *
		 * @param length Length of the code.
		**/
		public AuthenticationCodeTypeCall(int length) {
			this.length = length;
		}

		/**
		 * An authentication code is delivered via a phone call to the specified phone number.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AuthenticationCodeTypeCall(DataInput input) throws IOException {
			this.length = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AuthenticationCodeTypeCall.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AuthenticationCodeTypeCall.CONSTRUCTOR);
			output.writeInt(this.length);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AuthenticationCodeTypeCall authenticationCodeTypeCall = (AuthenticationCodeTypeCall) o;
			if (this.length != authenticationCodeTypeCall.length) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.length);
		}
	}

	/**
	 * An authentication code is delivered by an immediately canceled call
	 * to the specified phone number. The phone number that calls is the
	 * code that must be entered automatically.
	**/
	public static final class AuthenticationCodeTypeFlashCall extends AuthenticationCodeType {


		/**
		 * Pattern of the phone number from which the call will be made.
		**/
		public String pattern;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1395882402;

		/**
		 * An authentication code is delivered by an immediately canceled call to the specified phone number. The phone number that calls is the code that must be entered automatically.
		**/
		public AuthenticationCodeTypeFlashCall() {}

		/**
		 * An authentication code is delivered by an immediately canceled call to the specified phone number. The phone number that calls is the code that must be entered automatically.
		 *
		 * @param pattern Pattern of the phone number from which the call will be made.
		**/
		public AuthenticationCodeTypeFlashCall(String pattern) {
			this.pattern = pattern;
		}

		/**
		 * An authentication code is delivered by an immediately canceled call to the specified phone number. The phone number that calls is the code that must be entered automatically.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AuthenticationCodeTypeFlashCall(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] patternTmp = new byte[input.readInt()];
				input.readFully(patternTmp);
				this.pattern = new String(patternTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AuthenticationCodeTypeFlashCall.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AuthenticationCodeTypeFlashCall.CONSTRUCTOR);
			if (this.pattern == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] patternTmp = this.pattern.getBytes(StandardCharsets.UTF_8);
				output.writeInt(patternTmp.length);
				output.write(patternTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AuthenticationCodeTypeFlashCall authenticationCodeTypeFlashCall = (AuthenticationCodeTypeFlashCall) o;
			if (this.pattern != authenticationCodeTypeFlashCall.pattern) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.pattern == null ? 0 : this.pattern.hashCode();
		}
	}

	/**
	 * An authentication code is delivered by an immediately canceled call
	 * to the specified phone number. The last digits of the phone number
	 * that calls are the code that must be entered manually by the user.
	**/
	public static final class AuthenticationCodeTypeMissedCall extends AuthenticationCodeType {


		/**
		 * Prefix of the phone number from which the call will be made.
		**/
		public String phoneNumberPrefix;

		/**
		 * Number of digits in the code, excluding the prefix.
		**/
		public int length;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 700123783;

		/**
		 * An authentication code is delivered by an immediately canceled call to the specified phone number. The last digits of the phone number that calls are the code that must be entered manually by the user.
		**/
		public AuthenticationCodeTypeMissedCall() {}

		/**
		 * An authentication code is delivered by an immediately canceled call to the specified phone number. The last digits of the phone number that calls are the code that must be entered manually by the user.
		 *
		 * @param phoneNumberPrefix Prefix of the phone number from which the call will be made.
		 * @param length Number of digits in the code, excluding the prefix.
		**/
		public AuthenticationCodeTypeMissedCall(String phoneNumberPrefix, int length) {
			this.phoneNumberPrefix = phoneNumberPrefix;
			this.length = length;
		}

		/**
		 * An authentication code is delivered by an immediately canceled call to the specified phone number. The last digits of the phone number that calls are the code that must be entered manually by the user.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AuthenticationCodeTypeMissedCall(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] phoneNumberPrefixTmp = new byte[input.readInt()];
				input.readFully(phoneNumberPrefixTmp);
				this.phoneNumberPrefix = new String(phoneNumberPrefixTmp, StandardCharsets.UTF_8);
			}
			this.length = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AuthenticationCodeTypeMissedCall.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AuthenticationCodeTypeMissedCall.CONSTRUCTOR);
			if (this.phoneNumberPrefix == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] phoneNumberPrefixTmp = this.phoneNumberPrefix.getBytes(StandardCharsets.UTF_8);
				output.writeInt(phoneNumberPrefixTmp.length);
				output.write(phoneNumberPrefixTmp);
			}
			output.writeInt(this.length);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AuthenticationCodeTypeMissedCall authenticationCodeTypeMissedCall = (AuthenticationCodeTypeMissedCall) o;
			if (this.phoneNumberPrefix != authenticationCodeTypeMissedCall.phoneNumberPrefix) {
				return false;
			}
			if (this.length != authenticationCodeTypeMissedCall.length) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.length);
			result = result * 31 + (this.phoneNumberPrefix == null ? 0 : this.phoneNumberPrefix.hashCode());
			return result;
		}
	}

	/**
	 * An authentication code is delivered to https://fragment.com. The user
	 * must be logged in there via a wallet owning the phone number&#039;s
	 * NFT.
	**/
	public static final class AuthenticationCodeTypeFragment extends AuthenticationCodeType {


		/**
		 * URL to open to receive the code.
		**/
		public String url;

		/**
		 * Length of the code.
		**/
		public int length;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2129693491;

		/**
		 * An authentication code is delivered to https://fragment.com. The user must be logged in there via a wallet owning the phone number&#039;s NFT.
		**/
		public AuthenticationCodeTypeFragment() {}

		/**
		 * An authentication code is delivered to https://fragment.com. The user must be logged in there via a wallet owning the phone number&#039;s NFT.
		 *
		 * @param url URL to open to receive the code.
		 * @param length Length of the code.
		**/
		public AuthenticationCodeTypeFragment(String url, int length) {
			this.url = url;
			this.length = length;
		}

		/**
		 * An authentication code is delivered to https://fragment.com. The user must be logged in there via a wallet owning the phone number&#039;s NFT.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AuthenticationCodeTypeFragment(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] urlTmp = new byte[input.readInt()];
				input.readFully(urlTmp);
				this.url = new String(urlTmp, StandardCharsets.UTF_8);
			}
			this.length = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AuthenticationCodeTypeFragment.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AuthenticationCodeTypeFragment.CONSTRUCTOR);
			if (this.url == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] urlTmp = this.url.getBytes(StandardCharsets.UTF_8);
				output.writeInt(urlTmp.length);
				output.write(urlTmp);
			}
			output.writeInt(this.length);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AuthenticationCodeTypeFragment authenticationCodeTypeFragment = (AuthenticationCodeTypeFragment) o;
			if (this.url != authenticationCodeTypeFragment.url) {
				return false;
			}
			if (this.length != authenticationCodeTypeFragment.length) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.length);
			result = result * 31 + (this.url == null ? 0 : this.url.hashCode());
			return result;
		}
	}

	/**
	 * An authentication code is delivered via Firebase Authentication to
	 * the official Android application.
	**/
	public static final class AuthenticationCodeTypeFirebaseAndroid extends AuthenticationCodeType {


		/**
		 * Nonce to pass to the SafetyNet Attestation API.
		**/
		public byte[] nonce;

		/**
		 * Length of the code.
		**/
		public int length;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1978562535;

		/**
		 * An authentication code is delivered via Firebase Authentication to the official Android application.
		**/
		public AuthenticationCodeTypeFirebaseAndroid() {}

		/**
		 * An authentication code is delivered via Firebase Authentication to the official Android application.
		 *
		 * @param nonce Nonce to pass to the SafetyNet Attestation API.
		 * @param length Length of the code.
		**/
		public AuthenticationCodeTypeFirebaseAndroid(byte[] nonce, int length) {
			this.nonce = nonce;
			this.length = length;
		}

		/**
		 * An authentication code is delivered via Firebase Authentication to the official Android application.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AuthenticationCodeTypeFirebaseAndroid(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.nonce = new byte[input.readInt()];
				input.readFully(this.nonce);
			}
			this.length = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AuthenticationCodeTypeFirebaseAndroid.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AuthenticationCodeTypeFirebaseAndroid.CONSTRUCTOR);
			if (this.nonce == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.nonce.length);
				output.write(this.nonce);
			}
			output.writeInt(this.length);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AuthenticationCodeTypeFirebaseAndroid authenticationCodeTypeFirebaseAndroid = (AuthenticationCodeTypeFirebaseAndroid) o;
			if (this.nonce != authenticationCodeTypeFirebaseAndroid.nonce) {
				return false;
			}
			if (this.length != authenticationCodeTypeFirebaseAndroid.length) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.length);
			result = result * 31 + (Arrays.hashCode(this.nonce));
			return result;
		}
	}

	/**
	 * An authentication code is delivered via Firebase Authentication to
	 * the official iOS application.
	**/
	public static final class AuthenticationCodeTypeFirebaseIos extends AuthenticationCodeType {


		/**
		 * Receipt of successful application token validation to compare with receipt from push notification.
		**/
		public String receipt;

		/**
		 * Time after the next authentication method is supposed to be used if verification push notification isn&#039;t received, in seconds.
		**/
		public int pushTimeout;

		/**
		 * Length of the code.
		**/
		public int length;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -11162989;

		/**
		 * An authentication code is delivered via Firebase Authentication to the official iOS application.
		**/
		public AuthenticationCodeTypeFirebaseIos() {}

		/**
		 * An authentication code is delivered via Firebase Authentication to the official iOS application.
		 *
		 * @param receipt Receipt of successful application token validation to compare with receipt from push notification.
		 * @param pushTimeout Time after the next authentication method is supposed to be used if verification push notification isn&#039;t received, in seconds.
		 * @param length Length of the code.
		**/
		public AuthenticationCodeTypeFirebaseIos(String receipt, int pushTimeout, int length) {
			this.receipt = receipt;
			this.pushTimeout = pushTimeout;
			this.length = length;
		}

		/**
		 * An authentication code is delivered via Firebase Authentication to the official iOS application.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AuthenticationCodeTypeFirebaseIos(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] receiptTmp = new byte[input.readInt()];
				input.readFully(receiptTmp);
				this.receipt = new String(receiptTmp, StandardCharsets.UTF_8);
			}
			this.pushTimeout = input.readInt();
			this.length = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AuthenticationCodeTypeFirebaseIos.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AuthenticationCodeTypeFirebaseIos.CONSTRUCTOR);
			if (this.receipt == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] receiptTmp = this.receipt.getBytes(StandardCharsets.UTF_8);
				output.writeInt(receiptTmp.length);
				output.write(receiptTmp);
			}
			output.writeInt(this.pushTimeout);
			output.writeInt(this.length);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AuthenticationCodeTypeFirebaseIos authenticationCodeTypeFirebaseIos = (AuthenticationCodeTypeFirebaseIos) o;
			if (this.receipt != authenticationCodeTypeFirebaseIos.receipt) {
				return false;
			}
			if (this.pushTimeout != authenticationCodeTypeFirebaseIos.pushTimeout) {
				return false;
			}
			if (this.length != authenticationCodeTypeFirebaseIos.length) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.pushTimeout);
			result = result * 31 + (this.receipt == null ? 0 : this.receipt.hashCode());
			return result;
		}
	}

	/**
	 * Initialization parameters are needed. Call setTdlibParameters to
	 * provide them.
	**/
	public static final class AuthorizationStateWaitTdlibParameters extends AuthorizationState {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 904720988;

		/**
		 * Initialization parameters are needed. Call setTdlibParameters to provide them.
		**/
		public AuthorizationStateWaitTdlibParameters() {}

		/**
		 * Initialization parameters are needed. Call setTdlibParameters to provide them.
		 *
		**/

		/**
		 * Initialization parameters are needed. Call setTdlibParameters to provide them.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AuthorizationStateWaitTdlibParameters(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AuthorizationStateWaitTdlibParameters.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AuthorizationStateWaitTdlibParameters.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return AuthorizationStateWaitTdlibParameters.CONSTRUCTOR;
		}
	}

	/**
	 * TDLib needs the user&#039;s phone number to authorize. Call
	 * setAuthenticationPhoneNumber to provide the phone number, or use
	 * requestQrCodeAuthentication or checkAuthenticationBotToken for other
	 * authentication options.
	**/
	public static final class AuthorizationStateWaitPhoneNumber extends AuthorizationState {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 306402531;

		/**
		 * TDLib needs the user&#039;s phone number to authorize. Call setAuthenticationPhoneNumber to provide the phone number, or use requestQrCodeAuthentication or checkAuthenticationBotToken for other authentication options.
		**/
		public AuthorizationStateWaitPhoneNumber() {}

		/**
		 * TDLib needs the user&#039;s phone number to authorize. Call setAuthenticationPhoneNumber to provide the phone number, or use requestQrCodeAuthentication or checkAuthenticationBotToken for other authentication options.
		 *
		**/

		/**
		 * TDLib needs the user&#039;s phone number to authorize. Call setAuthenticationPhoneNumber to provide the phone number, or use requestQrCodeAuthentication or checkAuthenticationBotToken for other authentication options.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AuthorizationStateWaitPhoneNumber(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AuthorizationStateWaitPhoneNumber.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AuthorizationStateWaitPhoneNumber.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return AuthorizationStateWaitPhoneNumber.CONSTRUCTOR;
		}
	}

	/**
	 * TDLib needs the user&#039;s email address to authorize. Call
	 * setAuthenticationEmailAddress to provide the email address, or
	 * directly call checkAuthenticationEmailCode with Apple ID/Google ID
	 * token if allowed.
	**/
	public static final class AuthorizationStateWaitEmailAddress extends AuthorizationState {


		/**
		 * True, if authorization through Apple ID is allowed.
		**/
		public boolean allowAppleId;

		/**
		 * True, if authorization through Google ID is allowed.
		**/
		public boolean allowGoogleId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1040478663;

		/**
		 * TDLib needs the user&#039;s email address to authorize. Call setAuthenticationEmailAddress to provide the email address, or directly call checkAuthenticationEmailCode with Apple ID/Google ID token if allowed.
		**/
		public AuthorizationStateWaitEmailAddress() {}

		/**
		 * TDLib needs the user&#039;s email address to authorize. Call setAuthenticationEmailAddress to provide the email address, or directly call checkAuthenticationEmailCode with Apple ID/Google ID token if allowed.
		 *
		 * @param allowAppleId True, if authorization through Apple ID is allowed.
		 * @param allowGoogleId True, if authorization through Google ID is allowed.
		**/
		public AuthorizationStateWaitEmailAddress(boolean allowAppleId, boolean allowGoogleId) {
			this.allowAppleId = allowAppleId;
			this.allowGoogleId = allowGoogleId;
		}

		/**
		 * TDLib needs the user&#039;s email address to authorize. Call setAuthenticationEmailAddress to provide the email address, or directly call checkAuthenticationEmailCode with Apple ID/Google ID token if allowed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AuthorizationStateWaitEmailAddress(DataInput input) throws IOException {
			this.allowAppleId = input.readBoolean();
			this.allowGoogleId = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AuthorizationStateWaitEmailAddress.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AuthorizationStateWaitEmailAddress.CONSTRUCTOR);
			output.writeBoolean(this.allowAppleId);
			output.writeBoolean(this.allowGoogleId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AuthorizationStateWaitEmailAddress authorizationStateWaitEmailAddress = (AuthorizationStateWaitEmailAddress) o;
			if (this.allowAppleId != authorizationStateWaitEmailAddress.allowAppleId) {
				return false;
			}
			if (this.allowGoogleId != authorizationStateWaitEmailAddress.allowGoogleId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.allowAppleId);
			return result;
		}
	}

	/**
	 * TDLib needs the user&#039;s authentication code sent to an email
	 * address to authorize. Call checkAuthenticationEmailCode to provide
	 * the code.
	**/
	public static final class AuthorizationStateWaitEmailCode extends AuthorizationState {


		/**
		 * True, if authorization through Apple ID is allowed.
		**/
		public boolean allowAppleId;

		/**
		 * True, if authorization through Google ID is allowed.
		**/
		public boolean allowGoogleId;

		/**
		 * Information about the sent authentication code.
		**/
		public EmailAddressAuthenticationCodeInfo codeInfo;

		/**
		 * Reset state of the email address; may be null if the email address can&#039;t be reset.
		**/
		public EmailAddressResetState emailAddressResetState;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1868627365;

		/**
		 * TDLib needs the user&#039;s authentication code sent to an email address to authorize. Call checkAuthenticationEmailCode to provide the code.
		**/
		public AuthorizationStateWaitEmailCode() {}

		/**
		 * TDLib needs the user&#039;s authentication code sent to an email address to authorize. Call checkAuthenticationEmailCode to provide the code.
		 *
		 * @param allowAppleId True, if authorization through Apple ID is allowed.
		 * @param allowGoogleId True, if authorization through Google ID is allowed.
		 * @param codeInfo Information about the sent authentication code.
		 * @param emailAddressResetState Reset state of the email address; may be null if the email address can&#039;t be reset.
		**/
		public AuthorizationStateWaitEmailCode(boolean allowAppleId,
				boolean allowGoogleId,
				EmailAddressAuthenticationCodeInfo codeInfo,
				EmailAddressResetState emailAddressResetState) {
			this.allowAppleId = allowAppleId;
			this.allowGoogleId = allowGoogleId;
			this.codeInfo = codeInfo;
			this.emailAddressResetState = emailAddressResetState;
		}

		/**
		 * TDLib needs the user&#039;s authentication code sent to an email address to authorize. Call checkAuthenticationEmailCode to provide the code.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AuthorizationStateWaitEmailCode(DataInput input) throws IOException {
			this.allowAppleId = input.readBoolean();
			this.allowGoogleId = input.readBoolean();
			if (input.readBoolean()) {
				if (EmailAddressAuthenticationCodeInfo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.codeInfo = new EmailAddressAuthenticationCodeInfo(input);
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case EmailAddressResetStateAvailable.CONSTRUCTOR: this.emailAddressResetState = new EmailAddressResetStateAvailable(input); break;
					case EmailAddressResetStatePending.CONSTRUCTOR: this.emailAddressResetState = new EmailAddressResetStatePending(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AuthorizationStateWaitEmailCode.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AuthorizationStateWaitEmailCode.CONSTRUCTOR);
			output.writeBoolean(this.allowAppleId);
			output.writeBoolean(this.allowGoogleId);
			if (this.codeInfo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.codeInfo.serialize(output);
			}
			if (this.emailAddressResetState == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.emailAddressResetState.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AuthorizationStateWaitEmailCode authorizationStateWaitEmailCode = (AuthorizationStateWaitEmailCode) o;
			if (this.allowAppleId != authorizationStateWaitEmailCode.allowAppleId) {
				return false;
			}
			if (this.allowGoogleId != authorizationStateWaitEmailCode.allowGoogleId) {
				return false;
			}
			if (!Objects.equals(this.codeInfo, authorizationStateWaitEmailCode.codeInfo)) {
				return false;
			}
			if (!Objects.equals(this.emailAddressResetState, authorizationStateWaitEmailCode.emailAddressResetState)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.allowAppleId);
			result = result * 31 + (this.codeInfo == null ? 0 : this.codeInfo.hashCode());
			result = result * 31 + (this.emailAddressResetState == null ? 0 : this.emailAddressResetState.hashCode());
			return result;
		}
	}

	/**
	 * TDLib needs the user&#039;s authentication code to authorize. Call
	 * checkAuthenticationCode to check the code.
	**/
	public static final class AuthorizationStateWaitCode extends AuthorizationState {


		/**
		 * Information about the authorization code that was sent.
		**/
		public AuthenticationCodeInfo codeInfo;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 52643073;

		/**
		 * TDLib needs the user&#039;s authentication code to authorize. Call checkAuthenticationCode to check the code.
		**/
		public AuthorizationStateWaitCode() {}

		/**
		 * TDLib needs the user&#039;s authentication code to authorize. Call checkAuthenticationCode to check the code.
		 *
		 * @param codeInfo Information about the authorization code that was sent.
		**/
		public AuthorizationStateWaitCode(AuthenticationCodeInfo codeInfo) {
			this.codeInfo = codeInfo;
		}

		/**
		 * TDLib needs the user&#039;s authentication code to authorize. Call checkAuthenticationCode to check the code.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AuthorizationStateWaitCode(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (AuthenticationCodeInfo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.codeInfo = new AuthenticationCodeInfo(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AuthorizationStateWaitCode.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AuthorizationStateWaitCode.CONSTRUCTOR);
			if (this.codeInfo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.codeInfo.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AuthorizationStateWaitCode authorizationStateWaitCode = (AuthorizationStateWaitCode) o;
			if (!Objects.equals(this.codeInfo, authorizationStateWaitCode.codeInfo)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.codeInfo == null ? 0 : this.codeInfo.hashCode();
		}
	}

	/**
	 * The user needs to confirm authorization on another logged in device
	 * by scanning a QR code with the provided link.
	**/
	public static final class AuthorizationStateWaitOtherDeviceConfirmation extends AuthorizationState {


		/**
		 * A tg:// URL for the QR code. The link will be updated frequently.
		**/
		public String link;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 860166378;

		/**
		 * The user needs to confirm authorization on another logged in device by scanning a QR code with the provided link.
		**/
		public AuthorizationStateWaitOtherDeviceConfirmation() {}

		/**
		 * The user needs to confirm authorization on another logged in device by scanning a QR code with the provided link.
		 *
		 * @param link A tg:// URL for the QR code. The link will be updated frequently.
		**/
		public AuthorizationStateWaitOtherDeviceConfirmation(String link) {
			this.link = link;
		}

		/**
		 * The user needs to confirm authorization on another logged in device by scanning a QR code with the provided link.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AuthorizationStateWaitOtherDeviceConfirmation(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] linkTmp = new byte[input.readInt()];
				input.readFully(linkTmp);
				this.link = new String(linkTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AuthorizationStateWaitOtherDeviceConfirmation.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AuthorizationStateWaitOtherDeviceConfirmation.CONSTRUCTOR);
			if (this.link == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] linkTmp = this.link.getBytes(StandardCharsets.UTF_8);
				output.writeInt(linkTmp.length);
				output.write(linkTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AuthorizationStateWaitOtherDeviceConfirmation authorizationStateWaitOtherDeviceConfirmation = (AuthorizationStateWaitOtherDeviceConfirmation) o;
			if (this.link != authorizationStateWaitOtherDeviceConfirmation.link) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.link == null ? 0 : this.link.hashCode();
		}
	}

	/**
	 * The user is unregistered and need to accept terms of service and
	 * enter their first name and last name to finish registration. Call
	 * registerUser to accept the terms of service and provide the data.
	**/
	public static final class AuthorizationStateWaitRegistration extends AuthorizationState {


		/**
		 * Telegram terms of service.
		**/
		public TermsOfService termsOfService;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 550350511;

		/**
		 * The user is unregistered and need to accept terms of service and enter their first name and last name to finish registration. Call registerUser to accept the terms of service and provide the data.
		**/
		public AuthorizationStateWaitRegistration() {}

		/**
		 * The user is unregistered and need to accept terms of service and enter their first name and last name to finish registration. Call registerUser to accept the terms of service and provide the data.
		 *
		 * @param termsOfService Telegram terms of service.
		**/
		public AuthorizationStateWaitRegistration(TermsOfService termsOfService) {
			this.termsOfService = termsOfService;
		}

		/**
		 * The user is unregistered and need to accept terms of service and enter their first name and last name to finish registration. Call registerUser to accept the terms of service and provide the data.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AuthorizationStateWaitRegistration(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (TermsOfService.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.termsOfService = new TermsOfService(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AuthorizationStateWaitRegistration.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AuthorizationStateWaitRegistration.CONSTRUCTOR);
			if (this.termsOfService == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.termsOfService.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AuthorizationStateWaitRegistration authorizationStateWaitRegistration = (AuthorizationStateWaitRegistration) o;
			if (!Objects.equals(this.termsOfService, authorizationStateWaitRegistration.termsOfService)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.termsOfService == null ? 0 : this.termsOfService.hashCode();
		}
	}

	/**
	 * The user has been authorized, but needs to enter a 2-step
	 * verification password to start using the application. Call
	 * checkAuthenticationPassword to provide the password, or
	 * requestAuthenticationPasswordRecovery to recover the password, or
	 * deleteAccount to delete the account after a week.
	**/
	public static final class AuthorizationStateWaitPassword extends AuthorizationState {


		/**
		 * Hint for the password; may be empty.
		**/
		public String passwordHint;

		/**
		 * True, if a recovery email address has been set up.
		**/
		public boolean hasRecoveryEmailAddress;

		/**
		 * True, if some Telegram Passport elements were saved.
		**/
		public boolean hasPassportData;

		/**
		 * Pattern of the email address to which the recovery email was sent; empty until a recovery email has been sent.
		**/
		public String recoveryEmailAddressPattern;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 112238030;

		/**
		 * The user has been authorized, but needs to enter a 2-step verification password to start using the application. Call checkAuthenticationPassword to provide the password, or requestAuthenticationPasswordRecovery to recover the password, or deleteAccount to delete the account after a week.
		**/
		public AuthorizationStateWaitPassword() {}

		/**
		 * The user has been authorized, but needs to enter a 2-step verification password to start using the application. Call checkAuthenticationPassword to provide the password, or requestAuthenticationPasswordRecovery to recover the password, or deleteAccount to delete the account after a week.
		 *
		 * @param passwordHint Hint for the password; may be empty.
		 * @param hasRecoveryEmailAddress True, if a recovery email address has been set up.
		 * @param hasPassportData True, if some Telegram Passport elements were saved.
		 * @param recoveryEmailAddressPattern Pattern of the email address to which the recovery email was sent; empty until a recovery email has been sent.
		**/
		public AuthorizationStateWaitPassword(String passwordHint,
				boolean hasRecoveryEmailAddress,
				boolean hasPassportData,
				String recoveryEmailAddressPattern) {
			this.passwordHint = passwordHint;
			this.hasRecoveryEmailAddress = hasRecoveryEmailAddress;
			this.hasPassportData = hasPassportData;
			this.recoveryEmailAddressPattern = recoveryEmailAddressPattern;
		}

		/**
		 * The user has been authorized, but needs to enter a 2-step verification password to start using the application. Call checkAuthenticationPassword to provide the password, or requestAuthenticationPasswordRecovery to recover the password, or deleteAccount to delete the account after a week.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AuthorizationStateWaitPassword(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] passwordHintTmp = new byte[input.readInt()];
				input.readFully(passwordHintTmp);
				this.passwordHint = new String(passwordHintTmp, StandardCharsets.UTF_8);
			}
			this.hasRecoveryEmailAddress = input.readBoolean();
			this.hasPassportData = input.readBoolean();
			if (input.readBoolean()) {
				byte[] recoveryEmailAddressPatternTmp = new byte[input.readInt()];
				input.readFully(recoveryEmailAddressPatternTmp);
				this.recoveryEmailAddressPattern = new String(recoveryEmailAddressPatternTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AuthorizationStateWaitPassword.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AuthorizationStateWaitPassword.CONSTRUCTOR);
			if (this.passwordHint == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] passwordHintTmp = this.passwordHint.getBytes(StandardCharsets.UTF_8);
				output.writeInt(passwordHintTmp.length);
				output.write(passwordHintTmp);
			}
			output.writeBoolean(this.hasRecoveryEmailAddress);
			output.writeBoolean(this.hasPassportData);
			if (this.recoveryEmailAddressPattern == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] recoveryEmailAddressPatternTmp = this.recoveryEmailAddressPattern.getBytes(StandardCharsets.UTF_8);
				output.writeInt(recoveryEmailAddressPatternTmp.length);
				output.write(recoveryEmailAddressPatternTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AuthorizationStateWaitPassword authorizationStateWaitPassword = (AuthorizationStateWaitPassword) o;
			if (this.passwordHint != authorizationStateWaitPassword.passwordHint) {
				return false;
			}
			if (this.hasRecoveryEmailAddress != authorizationStateWaitPassword.hasRecoveryEmailAddress) {
				return false;
			}
			if (this.hasPassportData != authorizationStateWaitPassword.hasPassportData) {
				return false;
			}
			if (this.recoveryEmailAddressPattern != authorizationStateWaitPassword.recoveryEmailAddressPattern) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.hasRecoveryEmailAddress);
			result = result * 31 + (this.passwordHint == null ? 0 : this.passwordHint.hashCode());
			result = result * 31 + (this.recoveryEmailAddressPattern == null ? 0 : this.recoveryEmailAddressPattern.hashCode());
			return result;
		}
	}

	/**
	 * The user has been successfully authorized. TDLib is now ready to
	 * answer general requests.
	**/
	public static final class AuthorizationStateReady extends AuthorizationState {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1834871737;

		/**
		 * The user has been successfully authorized. TDLib is now ready to answer general requests.
		**/
		public AuthorizationStateReady() {}

		/**
		 * The user has been successfully authorized. TDLib is now ready to answer general requests.
		 *
		**/

		/**
		 * The user has been successfully authorized. TDLib is now ready to answer general requests.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AuthorizationStateReady(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AuthorizationStateReady.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AuthorizationStateReady.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return AuthorizationStateReady.CONSTRUCTOR;
		}
	}

	/**
	 * The user is currently logging out.
	**/
	public static final class AuthorizationStateLoggingOut extends AuthorizationState {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 154449270;

		/**
		 * The user is currently logging out.
		**/
		public AuthorizationStateLoggingOut() {}

		/**
		 * The user is currently logging out.
		 *
		**/

		/**
		 * The user is currently logging out.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AuthorizationStateLoggingOut(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AuthorizationStateLoggingOut.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AuthorizationStateLoggingOut.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return AuthorizationStateLoggingOut.CONSTRUCTOR;
		}
	}

	/**
	 * TDLib is closing, all subsequent queries will be answered with the
	 * error 500. Note that closing TDLib can take a while. All resources
	 * will be freed only after authorizationStateClosed has been received.
	**/
	public static final class AuthorizationStateClosing extends AuthorizationState {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 445855311;

		/**
		 * TDLib is closing, all subsequent queries will be answered with the error 500. Note that closing TDLib can take a while. All resources will be freed only after authorizationStateClosed has been received.
		**/
		public AuthorizationStateClosing() {}

		/**
		 * TDLib is closing, all subsequent queries will be answered with the error 500. Note that closing TDLib can take a while. All resources will be freed only after authorizationStateClosed has been received.
		 *
		**/

		/**
		 * TDLib is closing, all subsequent queries will be answered with the error 500. Note that closing TDLib can take a while. All resources will be freed only after authorizationStateClosed has been received.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AuthorizationStateClosing(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AuthorizationStateClosing.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AuthorizationStateClosing.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return AuthorizationStateClosing.CONSTRUCTOR;
		}
	}

	/**
	 * TDLib client is in its final state. All databases are closed and all
	 * resources are released. No other updates will be received after this.
	 * All queries will be responded to with error code 500. To continue
	 * working, one must create a new instance of the TDLib client.
	**/
	public static final class AuthorizationStateClosed extends AuthorizationState {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1526047584;

		/**
		 * TDLib client is in its final state. All databases are closed and all resources are released. No other updates will be received after this. All queries will be responded to with error code 500. To continue working, one must create a new instance of the TDLib client.
		**/
		public AuthorizationStateClosed() {}

		/**
		 * TDLib client is in its final state. All databases are closed and all resources are released. No other updates will be received after this. All queries will be responded to with error code 500. To continue working, one must create a new instance of the TDLib client.
		 *
		**/

		/**
		 * TDLib client is in its final state. All databases are closed and all resources are released. No other updates will be received after this. All queries will be responded to with error code 500. To continue working, one must create a new instance of the TDLib client.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AuthorizationStateClosed(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AuthorizationStateClosed.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AuthorizationStateClosed.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return AuthorizationStateClosed.CONSTRUCTOR;
		}
	}

	/**
	 * Contains auto-download settings.
	**/
	public static final class AutoDownloadSettings extends Object {


		/**
		 * True, if the auto-download is enabled.
		**/
		public boolean isAutoDownloadEnabled;

		/**
		 * The maximum size of a photo file to be auto-downloaded, in bytes.
		**/
		public int maxPhotoFileSize;

		/**
		 * The maximum size of a video file to be auto-downloaded, in bytes.
		**/
		public long maxVideoFileSize;

		/**
		 * The maximum size of other file types to be auto-downloaded, in bytes.
		**/
		public long maxOtherFileSize;

		/**
		 * The maximum suggested bitrate for uploaded videos, in kbit/s.
		**/
		public int videoUploadBitrate;

		/**
		 * True, if the beginning of video files needs to be preloaded for instant playback.
		**/
		public boolean preloadLargeVideos;

		/**
		 * True, if the next audio track needs to be preloaded while the user is listening to an audio file.
		**/
		public boolean preloadNextAudio;

		/**
		 * True, if &quot;use less data for calls&quot; option needs to be enabled.
		**/
		public boolean useLessDataForCalls;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -813805749;

		/**
		 * Contains auto-download settings.
		**/
		public AutoDownloadSettings() {}

		/**
		 * Contains auto-download settings.
		 *
		 * @param isAutoDownloadEnabled True, if the auto-download is enabled.
		 * @param maxPhotoFileSize The maximum size of a photo file to be auto-downloaded, in bytes.
		 * @param maxVideoFileSize The maximum size of a video file to be auto-downloaded, in bytes.
		 * @param maxOtherFileSize The maximum size of other file types to be auto-downloaded, in bytes.
		 * @param videoUploadBitrate The maximum suggested bitrate for uploaded videos, in kbit/s.
		 * @param preloadLargeVideos True, if the beginning of video files needs to be preloaded for instant playback.
		 * @param preloadNextAudio True, if the next audio track needs to be preloaded while the user is listening to an audio file.
		 * @param useLessDataForCalls True, if &quot;use less data for calls&quot; option needs to be enabled.
		**/
		public AutoDownloadSettings(boolean isAutoDownloadEnabled,
				int maxPhotoFileSize,
				long maxVideoFileSize,
				long maxOtherFileSize,
				int videoUploadBitrate,
				boolean preloadLargeVideos,
				boolean preloadNextAudio,
				boolean useLessDataForCalls) {
			this.isAutoDownloadEnabled = isAutoDownloadEnabled;
			this.maxPhotoFileSize = maxPhotoFileSize;
			this.maxVideoFileSize = maxVideoFileSize;
			this.maxOtherFileSize = maxOtherFileSize;
			this.videoUploadBitrate = videoUploadBitrate;
			this.preloadLargeVideos = preloadLargeVideos;
			this.preloadNextAudio = preloadNextAudio;
			this.useLessDataForCalls = useLessDataForCalls;
		}

		/**
		 * Contains auto-download settings.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AutoDownloadSettings(DataInput input) throws IOException {
			this.isAutoDownloadEnabled = input.readBoolean();
			this.maxPhotoFileSize = input.readInt();
			this.maxVideoFileSize = input.readLong();
			this.maxOtherFileSize = input.readLong();
			this.videoUploadBitrate = input.readInt();
			this.preloadLargeVideos = input.readBoolean();
			this.preloadNextAudio = input.readBoolean();
			this.useLessDataForCalls = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AutoDownloadSettings.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AutoDownloadSettings.CONSTRUCTOR);
			output.writeBoolean(this.isAutoDownloadEnabled);
			output.writeInt(this.maxPhotoFileSize);
			output.writeLong(this.maxVideoFileSize);
			output.writeLong(this.maxOtherFileSize);
			output.writeInt(this.videoUploadBitrate);
			output.writeBoolean(this.preloadLargeVideos);
			output.writeBoolean(this.preloadNextAudio);
			output.writeBoolean(this.useLessDataForCalls);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AutoDownloadSettings autoDownloadSettings = (AutoDownloadSettings) o;
			if (this.isAutoDownloadEnabled != autoDownloadSettings.isAutoDownloadEnabled) {
				return false;
			}
			if (this.maxPhotoFileSize != autoDownloadSettings.maxPhotoFileSize) {
				return false;
			}
			if (this.maxVideoFileSize != autoDownloadSettings.maxVideoFileSize) {
				return false;
			}
			if (this.maxOtherFileSize != autoDownloadSettings.maxOtherFileSize) {
				return false;
			}
			if (this.videoUploadBitrate != autoDownloadSettings.videoUploadBitrate) {
				return false;
			}
			if (this.preloadLargeVideos != autoDownloadSettings.preloadLargeVideos) {
				return false;
			}
			if (this.preloadNextAudio != autoDownloadSettings.preloadNextAudio) {
				return false;
			}
			if (this.useLessDataForCalls != autoDownloadSettings.useLessDataForCalls) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isAutoDownloadEnabled);
			return result;
		}
	}

	/**
	 * Contains auto-download settings presets for the current user.
	**/
	public static final class AutoDownloadSettingsPresets extends Object {


		/**
		 * Preset with lowest settings; supposed to be used by default when roaming.
		**/
		public AutoDownloadSettings low;

		/**
		 * Preset with medium settings; supposed to be used by default when using mobile data.
		**/
		public AutoDownloadSettings medium;

		/**
		 * Preset with highest settings; supposed to be used by default when connected on Wi-Fi.
		**/
		public AutoDownloadSettings high;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -782099166;

		/**
		 * Contains auto-download settings presets for the current user.
		**/
		public AutoDownloadSettingsPresets() {}

		/**
		 * Contains auto-download settings presets for the current user.
		 *
		 * @param low Preset with lowest settings; supposed to be used by default when roaming.
		 * @param medium Preset with medium settings; supposed to be used by default when using mobile data.
		 * @param high Preset with highest settings; supposed to be used by default when connected on Wi-Fi.
		**/
		public AutoDownloadSettingsPresets(AutoDownloadSettings low,
				AutoDownloadSettings medium,
				AutoDownloadSettings high) {
			this.low = low;
			this.medium = medium;
			this.high = high;
		}

		/**
		 * Contains auto-download settings presets for the current user.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AutoDownloadSettingsPresets(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (AutoDownloadSettings.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.low = new AutoDownloadSettings(input);
			}
			if (input.readBoolean()) {
				if (AutoDownloadSettings.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.medium = new AutoDownloadSettings(input);
			}
			if (input.readBoolean()) {
				if (AutoDownloadSettings.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.high = new AutoDownloadSettings(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AutoDownloadSettingsPresets.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AutoDownloadSettingsPresets.CONSTRUCTOR);
			if (this.low == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.low.serialize(output);
			}
			if (this.medium == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.medium.serialize(output);
			}
			if (this.high == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.high.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AutoDownloadSettingsPresets autoDownloadSettingsPresets = (AutoDownloadSettingsPresets) o;
			if (!Objects.equals(this.low, autoDownloadSettingsPresets.low)) {
				return false;
			}
			if (!Objects.equals(this.medium, autoDownloadSettingsPresets.medium)) {
				return false;
			}
			if (!Objects.equals(this.high, autoDownloadSettingsPresets.high)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.low == null ? 0 : this.low.hashCode();
			result = result * 31 + (this.medium == null ? 0 : this.medium.hashCode());
			result = result * 31 + (this.high == null ? 0 : this.high.hashCode());
			return result;
		}
	}

	/**
	 * Describes autosave settings.
	**/
	public static final class AutosaveSettings extends Object {


		/**
		 * Default autosave settings for private chats.
		**/
		public ScopeAutosaveSettings privateChatSettings;

		/**
		 * Default autosave settings for basic group and supergroup chats.
		**/
		public ScopeAutosaveSettings groupSettings;

		/**
		 * Default autosave settings for channel chats.
		**/
		public ScopeAutosaveSettings channelSettings;

		/**
		 * Autosave settings for specific chats.
		**/
		public AutosaveSettingsException[] exceptions;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1629412502;

		/**
		 * Describes autosave settings.
		**/
		public AutosaveSettings() {}

		/**
		 * Describes autosave settings.
		 *
		 * @param privateChatSettings Default autosave settings for private chats.
		 * @param groupSettings Default autosave settings for basic group and supergroup chats.
		 * @param channelSettings Default autosave settings for channel chats.
		 * @param exceptions Autosave settings for specific chats.
		**/
		public AutosaveSettings(ScopeAutosaveSettings privateChatSettings,
				ScopeAutosaveSettings groupSettings,
				ScopeAutosaveSettings channelSettings,
				AutosaveSettingsException[] exceptions) {
			this.privateChatSettings = privateChatSettings;
			this.groupSettings = groupSettings;
			this.channelSettings = channelSettings;
			this.exceptions = exceptions;
		}

		/**
		 * Describes autosave settings.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AutosaveSettings(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (ScopeAutosaveSettings.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.privateChatSettings = new ScopeAutosaveSettings(input);
			}
			if (input.readBoolean()) {
				if (ScopeAutosaveSettings.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.groupSettings = new ScopeAutosaveSettings(input);
			}
			if (input.readBoolean()) {
				if (ScopeAutosaveSettings.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.channelSettings = new ScopeAutosaveSettings(input);
			}
			if (input.readBoolean()) {
				this.exceptions = new AutosaveSettingsException[input.readInt()];
				for (int i = 0; i < this.exceptions.length; i++) {
					if (AutosaveSettingsException.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.exceptions[i] = new AutosaveSettingsException(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AutosaveSettings.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AutosaveSettings.CONSTRUCTOR);
			if (this.privateChatSettings == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.privateChatSettings.serialize(output);
			}
			if (this.groupSettings == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.groupSettings.serialize(output);
			}
			if (this.channelSettings == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.channelSettings.serialize(output);
			}
			if (this.exceptions == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.exceptions.length);
				for (int i = 0; i < this.exceptions.length; i++) {
					this.exceptions[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AutosaveSettings autosaveSettings = (AutosaveSettings) o;
			if (!Objects.equals(this.privateChatSettings, autosaveSettings.privateChatSettings)) {
				return false;
			}
			if (!Objects.equals(this.groupSettings, autosaveSettings.groupSettings)) {
				return false;
			}
			if (!Objects.equals(this.channelSettings, autosaveSettings.channelSettings)) {
				return false;
			}
			if (!Arrays.equals(this.exceptions, autosaveSettings.exceptions)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.privateChatSettings == null ? 0 : this.privateChatSettings.hashCode();
			result = result * 31 + (this.groupSettings == null ? 0 : this.groupSettings.hashCode());
			result = result * 31 + (this.channelSettings == null ? 0 : this.channelSettings.hashCode());
			result = result * 31 + (Arrays.hashCode(this.exceptions));
			return result;
		}
	}

	/**
	 * Contains autosave settings for a chat, which overrides default
	 * settings for the corresponding scope.
	**/
	public static final class AutosaveSettingsException extends Object {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Autosave settings for the chat.
		**/
		public ScopeAutosaveSettings settings;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1483470280;

		/**
		 * Contains autosave settings for a chat, which overrides default settings for the corresponding scope.
		**/
		public AutosaveSettingsException() {}

		/**
		 * Contains autosave settings for a chat, which overrides default settings for the corresponding scope.
		 *
		 * @param chatId Chat identifier.
		 * @param settings Autosave settings for the chat.
		**/
		public AutosaveSettingsException(long chatId, ScopeAutosaveSettings settings) {
			this.chatId = chatId;
			this.settings = settings;
		}

		/**
		 * Contains autosave settings for a chat, which overrides default settings for the corresponding scope.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AutosaveSettingsException(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				if (ScopeAutosaveSettings.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.settings = new ScopeAutosaveSettings(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AutosaveSettingsException.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AutosaveSettingsException.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.settings == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.settings.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AutosaveSettingsException autosaveSettingsException = (AutosaveSettingsException) o;
			if (this.chatId != autosaveSettingsException.chatId) {
				return false;
			}
			if (!Objects.equals(this.settings, autosaveSettingsException.settings)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.settings == null ? 0 : this.settings.hashCode());
			return result;
		}
	}

	/**
	 * Autosave settings applied to all private chats without chat-specific
	 * settings.
	**/
	public static final class AutosaveSettingsScopePrivateChats extends AutosaveSettingsScope {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1395227007;

		/**
		 * Autosave settings applied to all private chats without chat-specific settings.
		**/
		public AutosaveSettingsScopePrivateChats() {}

		/**
		 * Autosave settings applied to all private chats without chat-specific settings.
		 *
		**/

		/**
		 * Autosave settings applied to all private chats without chat-specific settings.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AutosaveSettingsScopePrivateChats(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AutosaveSettingsScopePrivateChats.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AutosaveSettingsScopePrivateChats.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return AutosaveSettingsScopePrivateChats.CONSTRUCTOR;
		}
	}

	/**
	 * Autosave settings applied to all basic group and supergroup chats
	 * without chat-specific settings.
	**/
	public static final class AutosaveSettingsScopeGroupChats extends AutosaveSettingsScope {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 853544526;

		/**
		 * Autosave settings applied to all basic group and supergroup chats without chat-specific settings.
		**/
		public AutosaveSettingsScopeGroupChats() {}

		/**
		 * Autosave settings applied to all basic group and supergroup chats without chat-specific settings.
		 *
		**/

		/**
		 * Autosave settings applied to all basic group and supergroup chats without chat-specific settings.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AutosaveSettingsScopeGroupChats(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AutosaveSettingsScopeGroupChats.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AutosaveSettingsScopeGroupChats.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return AutosaveSettingsScopeGroupChats.CONSTRUCTOR;
		}
	}

	/**
	 * Autosave settings applied to all channel chats without chat-specific
	 * settings.
	**/
	public static final class AutosaveSettingsScopeChannelChats extends AutosaveSettingsScope {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -499572783;

		/**
		 * Autosave settings applied to all channel chats without chat-specific settings.
		**/
		public AutosaveSettingsScopeChannelChats() {}

		/**
		 * Autosave settings applied to all channel chats without chat-specific settings.
		 *
		**/

		/**
		 * Autosave settings applied to all channel chats without chat-specific settings.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AutosaveSettingsScopeChannelChats(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AutosaveSettingsScopeChannelChats.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AutosaveSettingsScopeChannelChats.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return AutosaveSettingsScopeChannelChats.CONSTRUCTOR;
		}
	}

	/**
	 * Autosave settings applied to a chat.
	**/
	public static final class AutosaveSettingsScopeChat extends AutosaveSettingsScope {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1632255255;

		/**
		 * Autosave settings applied to a chat.
		**/
		public AutosaveSettingsScopeChat() {}

		/**
		 * Autosave settings applied to a chat.
		 *
		 * @param chatId Chat identifier.
		**/
		public AutosaveSettingsScopeChat(long chatId) {
			this.chatId = chatId;
		}

		/**
		 * Autosave settings applied to a chat.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AutosaveSettingsScopeChat(DataInput input) throws IOException {
			this.chatId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AutosaveSettingsScopeChat.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AutosaveSettingsScopeChat.CONSTRUCTOR);
			output.writeLong(this.chatId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AutosaveSettingsScopeChat autosaveSettingsScopeChat = (AutosaveSettingsScopeChat) o;
			if (this.chatId != autosaveSettingsScopeChat.chatId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.chatId);
		}
	}

	/**
	 * Represents an available reaction.
	**/
	public static final class AvailableReaction extends Object {


		/**
		 * Type of the reaction.
		**/
		public ReactionType type;

		/**
		 * True, if Telegram Premium is needed to send the reaction.
		**/
		public boolean needsPremium;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -117292153;

		/**
		 * Represents an available reaction.
		**/
		public AvailableReaction() {}

		/**
		 * Represents an available reaction.
		 *
		 * @param type Type of the reaction.
		 * @param needsPremium True, if Telegram Premium is needed to send the reaction.
		**/
		public AvailableReaction(ReactionType type, boolean needsPremium) {
			this.type = type;
			this.needsPremium = needsPremium;
		}

		/**
		 * Represents an available reaction.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AvailableReaction(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ReactionTypeEmoji.CONSTRUCTOR: this.type = new ReactionTypeEmoji(input); break;
					case ReactionTypeCustomEmoji.CONSTRUCTOR: this.type = new ReactionTypeCustomEmoji(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.needsPremium = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AvailableReaction.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AvailableReaction.CONSTRUCTOR);
			if (this.type == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.type.serialize(output);
			}
			output.writeBoolean(this.needsPremium);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AvailableReaction availableReaction = (AvailableReaction) o;
			if (!Objects.equals(this.type, availableReaction.type)) {
				return false;
			}
			if (this.needsPremium != availableReaction.needsPremium) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.needsPremium);
			result = result * 31 + (this.type == null ? 0 : this.type.hashCode());
			return result;
		}
	}

	/**
	 * Represents a list of reactions that can be added to a message.
	**/
	public static final class AvailableReactions extends Object {


		/**
		 * List of reactions to be shown at the top.
		**/
		public AvailableReaction[] topReactions;

		/**
		 * List of recently used reactions.
		**/
		public AvailableReaction[] recentReactions;

		/**
		 * List of popular reactions.
		**/
		public AvailableReaction[] popularReactions;

		/**
		 * True, if custom emoji reactions could be added by Telegram Premium subscribers.
		**/
		public boolean allowCustomEmoji;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1995943616;

		/**
		 * Represents a list of reactions that can be added to a message.
		**/
		public AvailableReactions() {}

		/**
		 * Represents a list of reactions that can be added to a message.
		 *
		 * @param topReactions List of reactions to be shown at the top.
		 * @param recentReactions List of recently used reactions.
		 * @param popularReactions List of popular reactions.
		 * @param allowCustomEmoji True, if custom emoji reactions could be added by Telegram Premium subscribers.
		**/
		public AvailableReactions(AvailableReaction[] topReactions,
				AvailableReaction[] recentReactions,
				AvailableReaction[] popularReactions,
				boolean allowCustomEmoji) {
			this.topReactions = topReactions;
			this.recentReactions = recentReactions;
			this.popularReactions = popularReactions;
			this.allowCustomEmoji = allowCustomEmoji;
		}

		/**
		 * Represents a list of reactions that can be added to a message.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AvailableReactions(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.topReactions = new AvailableReaction[input.readInt()];
				for (int i = 0; i < this.topReactions.length; i++) {
					if (AvailableReaction.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.topReactions[i] = new AvailableReaction(input);
				}
			}
			if (input.readBoolean()) {
				this.recentReactions = new AvailableReaction[input.readInt()];
				for (int i = 0; i < this.recentReactions.length; i++) {
					if (AvailableReaction.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.recentReactions[i] = new AvailableReaction(input);
				}
			}
			if (input.readBoolean()) {
				this.popularReactions = new AvailableReaction[input.readInt()];
				for (int i = 0; i < this.popularReactions.length; i++) {
					if (AvailableReaction.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.popularReactions[i] = new AvailableReaction(input);
				}
			}
			this.allowCustomEmoji = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AvailableReactions.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AvailableReactions.CONSTRUCTOR);
			if (this.topReactions == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.topReactions.length);
				for (int i = 0; i < this.topReactions.length; i++) {
					this.topReactions[i].serialize(output);
				}
			}
			if (this.recentReactions == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.recentReactions.length);
				for (int i = 0; i < this.recentReactions.length; i++) {
					this.recentReactions[i].serialize(output);
				}
			}
			if (this.popularReactions == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.popularReactions.length);
				for (int i = 0; i < this.popularReactions.length; i++) {
					this.popularReactions[i].serialize(output);
				}
			}
			output.writeBoolean(this.allowCustomEmoji);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AvailableReactions availableReactions = (AvailableReactions) o;
			if (!Arrays.equals(this.topReactions, availableReactions.topReactions)) {
				return false;
			}
			if (!Arrays.equals(this.recentReactions, availableReactions.recentReactions)) {
				return false;
			}
			if (!Arrays.equals(this.popularReactions, availableReactions.popularReactions)) {
				return false;
			}
			if (this.allowCustomEmoji != availableReactions.allowCustomEmoji) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.allowCustomEmoji);
			result = result * 31 + (Arrays.hashCode(this.topReactions));
			result = result * 31 + (Arrays.hashCode(this.recentReactions));
			result = result * 31 + (Arrays.hashCode(this.popularReactions));
			return result;
		}
	}

	/**
	 * Describes a chat background.
	**/
	public static final class Background extends Object {


		/**
		 * Unique background identifier.
		**/
		public long id;

		/**
		 * True, if this is one of default backgrounds.
		**/
		public boolean isDefault;

		/**
		 * True, if the background is dark and is recommended to be used with dark theme.
		**/
		public boolean isDark;

		/**
		 * Unique background name.
		**/
		public String name;

		/**
		 * Document with the background; may be null. Null only for filled backgrounds.
		**/
		public Document document;

		/**
		 * Type of the background.
		**/
		public BackgroundType type;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -429971172;

		/**
		 * Describes a chat background.
		**/
		public Background() {}

		/**
		 * Describes a chat background.
		 *
		 * @param id Unique background identifier.
		 * @param isDefault True, if this is one of default backgrounds.
		 * @param isDark True, if the background is dark and is recommended to be used with dark theme.
		 * @param name Unique background name.
		 * @param document Document with the background; may be null. Null only for filled backgrounds.
		 * @param type Type of the background.
		**/
		public Background(long id,
				boolean isDefault,
				boolean isDark,
				String name,
				Document document,
				BackgroundType type) {
			this.id = id;
			this.isDefault = isDefault;
			this.isDark = isDark;
			this.name = name;
			this.document = document;
			this.type = type;
		}

		/**
		 * Describes a chat background.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public Background(DataInput input) throws IOException {
			this.id = input.readLong();
			this.isDefault = input.readBoolean();
			this.isDark = input.readBoolean();
			if (input.readBoolean()) {
				byte[] nameTmp = new byte[input.readInt()];
				input.readFully(nameTmp);
				this.name = new String(nameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (Document.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.document = new Document(input);
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case BackgroundTypeWallpaper.CONSTRUCTOR: this.type = new BackgroundTypeWallpaper(input); break;
					case BackgroundTypePattern.CONSTRUCTOR: this.type = new BackgroundTypePattern(input); break;
					case BackgroundTypeFill.CONSTRUCTOR: this.type = new BackgroundTypeFill(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return Background.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(Background.CONSTRUCTOR);
			output.writeLong(this.id);
			output.writeBoolean(this.isDefault);
			output.writeBoolean(this.isDark);
			if (this.name == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nameTmp = this.name.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nameTmp.length);
				output.write(nameTmp);
			}
			if (this.document == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.document.serialize(output);
			}
			if (this.type == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.type.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			Background background = (Background) o;
			if (this.id != background.id) {
				return false;
			}
			if (this.isDefault != background.isDefault) {
				return false;
			}
			if (this.isDark != background.isDark) {
				return false;
			}
			if (this.name != background.name) {
				return false;
			}
			if (!Objects.equals(this.document, background.document)) {
				return false;
			}
			if (!Objects.equals(this.type, background.type)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.id);
			result = result * 31 + (this.name == null ? 0 : this.name.hashCode());
			result = result * 31 + (this.document == null ? 0 : this.document.hashCode());
			result = result * 31 + (this.type == null ? 0 : this.type.hashCode());
			return result;
		}
	}

	/**
	 * Describes a solid fill of a background.
	**/
	public static final class BackgroundFillSolid extends BackgroundFill {


		/**
		 * A color of the background in the RGB24 format.
		**/
		public int color;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1010678813;

		/**
		 * Describes a solid fill of a background.
		**/
		public BackgroundFillSolid() {}

		/**
		 * Describes a solid fill of a background.
		 *
		 * @param color A color of the background in the RGB24 format.
		**/
		public BackgroundFillSolid(int color) {
			this.color = color;
		}

		/**
		 * Describes a solid fill of a background.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public BackgroundFillSolid(DataInput input) throws IOException {
			this.color = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return BackgroundFillSolid.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(BackgroundFillSolid.CONSTRUCTOR);
			output.writeInt(this.color);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			BackgroundFillSolid backgroundFillSolid = (BackgroundFillSolid) o;
			if (this.color != backgroundFillSolid.color) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.color);
		}
	}

	/**
	 * Describes a gradient fill of a background.
	**/
	public static final class BackgroundFillGradient extends BackgroundFill {


		/**
		 * A top color of the background in the RGB24 format.
		**/
		public int topColor;

		/**
		 * A bottom color of the background in the RGB24 format.
		**/
		public int bottomColor;

		/**
		 * Clockwise rotation angle of the gradient, in degrees; 0-359. Must always be divisible by 45.
		**/
		public int rotationAngle;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1839206017;

		/**
		 * Describes a gradient fill of a background.
		**/
		public BackgroundFillGradient() {}

		/**
		 * Describes a gradient fill of a background.
		 *
		 * @param topColor A top color of the background in the RGB24 format.
		 * @param bottomColor A bottom color of the background in the RGB24 format.
		 * @param rotationAngle Clockwise rotation angle of the gradient, in degrees; 0-359. Must always be divisible by 45.
		**/
		public BackgroundFillGradient(int topColor, int bottomColor, int rotationAngle) {
			this.topColor = topColor;
			this.bottomColor = bottomColor;
			this.rotationAngle = rotationAngle;
		}

		/**
		 * Describes a gradient fill of a background.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public BackgroundFillGradient(DataInput input) throws IOException {
			this.topColor = input.readInt();
			this.bottomColor = input.readInt();
			this.rotationAngle = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return BackgroundFillGradient.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(BackgroundFillGradient.CONSTRUCTOR);
			output.writeInt(this.topColor);
			output.writeInt(this.bottomColor);
			output.writeInt(this.rotationAngle);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			BackgroundFillGradient backgroundFillGradient = (BackgroundFillGradient) o;
			if (this.topColor != backgroundFillGradient.topColor) {
				return false;
			}
			if (this.bottomColor != backgroundFillGradient.bottomColor) {
				return false;
			}
			if (this.rotationAngle != backgroundFillGradient.rotationAngle) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.topColor);
			return result;
		}
	}

	/**
	 * Describes a freeform gradient fill of a background.
	**/
	public static final class BackgroundFillFreeformGradient extends BackgroundFill {


		/**
		 * A list of 3 or 4 colors of the freeform gradients in the RGB24 format.
		**/
		public int[] colors;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1145469255;

		/**
		 * Describes a freeform gradient fill of a background.
		**/
		public BackgroundFillFreeformGradient() {}

		/**
		 * Describes a freeform gradient fill of a background.
		 *
		 * @param colors A list of 3 or 4 colors of the freeform gradients in the RGB24 format.
		**/
		public BackgroundFillFreeformGradient(int[] colors) {
			this.colors = colors;
		}

		/**
		 * Describes a freeform gradient fill of a background.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public BackgroundFillFreeformGradient(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.colors = new int[input.readInt()];
				for (int i = 0; i < this.colors.length; i++) {
					this.colors[i] = input.readInt();
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return BackgroundFillFreeformGradient.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(BackgroundFillFreeformGradient.CONSTRUCTOR);
			if (this.colors == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.colors.length);
				for (int i = 0; i < this.colors.length; i++) {
					output.writeInt(this.colors[i]);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			BackgroundFillFreeformGradient backgroundFillFreeformGradient = (BackgroundFillFreeformGradient) o;
			if (!Arrays.equals(this.colors, backgroundFillFreeformGradient.colors)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.colors);
		}
	}

	/**
	 * A wallpaper in JPEG format.
	**/
	public static final class BackgroundTypeWallpaper extends BackgroundType {


		/**
		 * True, if the wallpaper must be downscaled to fit in 450x450 square and then box-blurred with radius 12.
		**/
		public boolean isBlurred;

		/**
		 * True, if the background needs to be slightly moved when device is tilted.
		**/
		public boolean isMoving;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1972128891;

		/**
		 * A wallpaper in JPEG format.
		**/
		public BackgroundTypeWallpaper() {}

		/**
		 * A wallpaper in JPEG format.
		 *
		 * @param isBlurred True, if the wallpaper must be downscaled to fit in 450x450 square and then box-blurred with radius 12.
		 * @param isMoving True, if the background needs to be slightly moved when device is tilted.
		**/
		public BackgroundTypeWallpaper(boolean isBlurred, boolean isMoving) {
			this.isBlurred = isBlurred;
			this.isMoving = isMoving;
		}

		/**
		 * A wallpaper in JPEG format.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public BackgroundTypeWallpaper(DataInput input) throws IOException {
			this.isBlurred = input.readBoolean();
			this.isMoving = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return BackgroundTypeWallpaper.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(BackgroundTypeWallpaper.CONSTRUCTOR);
			output.writeBoolean(this.isBlurred);
			output.writeBoolean(this.isMoving);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			BackgroundTypeWallpaper backgroundTypeWallpaper = (BackgroundTypeWallpaper) o;
			if (this.isBlurred != backgroundTypeWallpaper.isBlurred) {
				return false;
			}
			if (this.isMoving != backgroundTypeWallpaper.isMoving) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isBlurred);
			return result;
		}
	}

	/**
	 * A PNG or TGV (gzipped subset of SVG with MIME type
	 * &quot;application/x-tgwallpattern&quot;) pattern to be combined with
	 * the background fill chosen by the user.
	**/
	public static final class BackgroundTypePattern extends BackgroundType {


		/**
		 * Fill of the background.
		**/
		public BackgroundFill fill;

		/**
		 * Intensity of the pattern when it is shown above the filled background; 0-100.
		**/
		public int intensity;

		/**
		 * True, if the background fill must be applied only to the pattern itself. All other pixels are black in this case. For dark themes only.
		**/
		public boolean isInverted;

		/**
		 * True, if the background needs to be slightly moved when device is tilted.
		**/
		public boolean isMoving;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1290213117;

		/**
		 * A PNG or TGV (gzipped subset of SVG with MIME type &quot;application/x-tgwallpattern&quot;) pattern to be combined with the background fill chosen by the user.
		**/
		public BackgroundTypePattern() {}

		/**
		 * A PNG or TGV (gzipped subset of SVG with MIME type &quot;application/x-tgwallpattern&quot;) pattern to be combined with the background fill chosen by the user.
		 *
		 * @param fill Fill of the background.
		 * @param intensity Intensity of the pattern when it is shown above the filled background; 0-100.
		 * @param isInverted True, if the background fill must be applied only to the pattern itself. All other pixels are black in this case. For dark themes only.
		 * @param isMoving True, if the background needs to be slightly moved when device is tilted.
		**/
		public BackgroundTypePattern(BackgroundFill fill,
				int intensity,
				boolean isInverted,
				boolean isMoving) {
			this.fill = fill;
			this.intensity = intensity;
			this.isInverted = isInverted;
			this.isMoving = isMoving;
		}

		/**
		 * A PNG or TGV (gzipped subset of SVG with MIME type &quot;application/x-tgwallpattern&quot;) pattern to be combined with the background fill chosen by the user.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public BackgroundTypePattern(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case BackgroundFillSolid.CONSTRUCTOR: this.fill = new BackgroundFillSolid(input); break;
					case BackgroundFillGradient.CONSTRUCTOR: this.fill = new BackgroundFillGradient(input); break;
					case BackgroundFillFreeformGradient.CONSTRUCTOR: this.fill = new BackgroundFillFreeformGradient(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.intensity = input.readInt();
			this.isInverted = input.readBoolean();
			this.isMoving = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return BackgroundTypePattern.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(BackgroundTypePattern.CONSTRUCTOR);
			if (this.fill == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.fill.serialize(output);
			}
			output.writeInt(this.intensity);
			output.writeBoolean(this.isInverted);
			output.writeBoolean(this.isMoving);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			BackgroundTypePattern backgroundTypePattern = (BackgroundTypePattern) o;
			if (!Objects.equals(this.fill, backgroundTypePattern.fill)) {
				return false;
			}
			if (this.intensity != backgroundTypePattern.intensity) {
				return false;
			}
			if (this.isInverted != backgroundTypePattern.isInverted) {
				return false;
			}
			if (this.isMoving != backgroundTypePattern.isMoving) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.intensity);
			result = result * 31 + (this.fill == null ? 0 : this.fill.hashCode());
			return result;
		}
	}

	/**
	 * A filled background.
	**/
	public static final class BackgroundTypeFill extends BackgroundType {


		/**
		 * The background fill.
		**/
		public BackgroundFill fill;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 993008684;

		/**
		 * A filled background.
		**/
		public BackgroundTypeFill() {}

		/**
		 * A filled background.
		 *
		 * @param fill The background fill.
		**/
		public BackgroundTypeFill(BackgroundFill fill) {
			this.fill = fill;
		}

		/**
		 * A filled background.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public BackgroundTypeFill(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case BackgroundFillSolid.CONSTRUCTOR: this.fill = new BackgroundFillSolid(input); break;
					case BackgroundFillGradient.CONSTRUCTOR: this.fill = new BackgroundFillGradient(input); break;
					case BackgroundFillFreeformGradient.CONSTRUCTOR: this.fill = new BackgroundFillFreeformGradient(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return BackgroundTypeFill.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(BackgroundTypeFill.CONSTRUCTOR);
			if (this.fill == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.fill.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			BackgroundTypeFill backgroundTypeFill = (BackgroundTypeFill) o;
			if (!Objects.equals(this.fill, backgroundTypeFill.fill)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.fill == null ? 0 : this.fill.hashCode();
		}
	}

	/**
	 * Contains a list of backgrounds.
	**/
	public static final class Backgrounds extends Object {


		/**
		 * A list of backgrounds.
		**/
		public Background[] backgrounds;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 724728704;

		/**
		 * Contains a list of backgrounds.
		**/
		public Backgrounds() {}

		/**
		 * Contains a list of backgrounds.
		 *
		 * @param backgrounds A list of backgrounds.
		**/
		public Backgrounds(Background[] backgrounds) {
			this.backgrounds = backgrounds;
		}

		/**
		 * Contains a list of backgrounds.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public Backgrounds(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.backgrounds = new Background[input.readInt()];
				for (int i = 0; i < this.backgrounds.length; i++) {
					if (Background.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.backgrounds[i] = new Background(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return Backgrounds.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(Backgrounds.CONSTRUCTOR);
			if (this.backgrounds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.backgrounds.length);
				for (int i = 0; i < this.backgrounds.length; i++) {
					this.backgrounds[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			Backgrounds backgrounds = (Backgrounds) o;
			if (!Arrays.equals(this.backgrounds, backgrounds.backgrounds)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.backgrounds);
		}
	}

	/**
	 * Describes an action associated with a bank card number.
	**/
	public static final class BankCardActionOpenUrl extends Object {


		/**
		 * Action text.
		**/
		public String text;

		/**
		 * The URL to be opened.
		**/
		public String url;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -196454267;

		/**
		 * Describes an action associated with a bank card number.
		**/
		public BankCardActionOpenUrl() {}

		/**
		 * Describes an action associated with a bank card number.
		 *
		 * @param text Action text.
		 * @param url The URL to be opened.
		**/
		public BankCardActionOpenUrl(String text, String url) {
			this.text = text;
			this.url = url;
		}

		/**
		 * Describes an action associated with a bank card number.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public BankCardActionOpenUrl(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] textTmp = new byte[input.readInt()];
				input.readFully(textTmp);
				this.text = new String(textTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] urlTmp = new byte[input.readInt()];
				input.readFully(urlTmp);
				this.url = new String(urlTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return BankCardActionOpenUrl.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(BankCardActionOpenUrl.CONSTRUCTOR);
			if (this.text == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] textTmp = this.text.getBytes(StandardCharsets.UTF_8);
				output.writeInt(textTmp.length);
				output.write(textTmp);
			}
			if (this.url == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] urlTmp = this.url.getBytes(StandardCharsets.UTF_8);
				output.writeInt(urlTmp.length);
				output.write(urlTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			BankCardActionOpenUrl bankCardActionOpenUrl = (BankCardActionOpenUrl) o;
			if (this.text != bankCardActionOpenUrl.text) {
				return false;
			}
			if (this.url != bankCardActionOpenUrl.url) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.text == null ? 0 : this.text.hashCode();
			result = result * 31 + (this.url == null ? 0 : this.url.hashCode());
			return result;
		}
	}

	/**
	 * Information about a bank card.
	**/
	public static final class BankCardInfo extends Object {


		/**
		 * Title of the bank card description.
		**/
		public String title;

		/**
		 * Actions that can be done with the bank card number.
		**/
		public BankCardActionOpenUrl[] actions;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2116647730;

		/**
		 * Information about a bank card.
		**/
		public BankCardInfo() {}

		/**
		 * Information about a bank card.
		 *
		 * @param title Title of the bank card description.
		 * @param actions Actions that can be done with the bank card number.
		**/
		public BankCardInfo(String title, BankCardActionOpenUrl[] actions) {
			this.title = title;
			this.actions = actions;
		}

		/**
		 * Information about a bank card.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public BankCardInfo(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				this.actions = new BankCardActionOpenUrl[input.readInt()];
				for (int i = 0; i < this.actions.length; i++) {
					if (BankCardActionOpenUrl.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.actions[i] = new BankCardActionOpenUrl(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return BankCardInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(BankCardInfo.CONSTRUCTOR);
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
			if (this.actions == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.actions.length);
				for (int i = 0; i < this.actions.length; i++) {
					this.actions[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			BankCardInfo bankCardInfo = (BankCardInfo) o;
			if (this.title != bankCardInfo.title) {
				return false;
			}
			if (!Arrays.equals(this.actions, bankCardInfo.actions)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.title == null ? 0 : this.title.hashCode();
			result = result * 31 + (Arrays.hashCode(this.actions));
			return result;
		}
	}

	/**
	 * Represents a basic group of 0-200 users (must be upgraded to a
	 * supergroup to accommodate more than 200 users).
	**/
	public static final class BasicGroup extends Object {


		/**
		 * Group identifier.
		**/
		public long id;

		/**
		 * Number of members in the group.
		**/
		public int memberCount;

		/**
		 * Status of the current user in the group.
		**/
		public ChatMemberStatus status;

		/**
		 * True, if the group is active.
		**/
		public boolean isActive;

		/**
		 * Identifier of the supergroup to which this group was upgraded; 0 if none.
		**/
		public long upgradedToSupergroupId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -194767217;

		/**
		 * Represents a basic group of 0-200 users (must be upgraded to a supergroup to accommodate more than 200 users).
		**/
		public BasicGroup() {}

		/**
		 * Represents a basic group of 0-200 users (must be upgraded to a supergroup to accommodate more than 200 users).
		 *
		 * @param id Group identifier.
		 * @param memberCount Number of members in the group.
		 * @param status Status of the current user in the group.
		 * @param isActive True, if the group is active.
		 * @param upgradedToSupergroupId Identifier of the supergroup to which this group was upgraded; 0 if none.
		**/
		public BasicGroup(long id,
				int memberCount,
				ChatMemberStatus status,
				boolean isActive,
				long upgradedToSupergroupId) {
			this.id = id;
			this.memberCount = memberCount;
			this.status = status;
			this.isActive = isActive;
			this.upgradedToSupergroupId = upgradedToSupergroupId;
		}

		/**
		 * Represents a basic group of 0-200 users (must be upgraded to a supergroup to accommodate more than 200 users).
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public BasicGroup(DataInput input) throws IOException {
			this.id = input.readLong();
			this.memberCount = input.readInt();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ChatMemberStatusCreator.CONSTRUCTOR: this.status = new ChatMemberStatusCreator(input); break;
					case ChatMemberStatusAdministrator.CONSTRUCTOR: this.status = new ChatMemberStatusAdministrator(input); break;
					case ChatMemberStatusMember.CONSTRUCTOR: this.status = new ChatMemberStatusMember(input); break;
					case ChatMemberStatusRestricted.CONSTRUCTOR: this.status = new ChatMemberStatusRestricted(input); break;
					case ChatMemberStatusLeft.CONSTRUCTOR: this.status = new ChatMemberStatusLeft(input); break;
					case ChatMemberStatusBanned.CONSTRUCTOR: this.status = new ChatMemberStatusBanned(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.isActive = input.readBoolean();
			this.upgradedToSupergroupId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return BasicGroup.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(BasicGroup.CONSTRUCTOR);
			output.writeLong(this.id);
			output.writeInt(this.memberCount);
			if (this.status == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.status.serialize(output);
			}
			output.writeBoolean(this.isActive);
			output.writeLong(this.upgradedToSupergroupId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			BasicGroup basicGroup = (BasicGroup) o;
			if (this.id != basicGroup.id) {
				return false;
			}
			if (this.memberCount != basicGroup.memberCount) {
				return false;
			}
			if (!Objects.equals(this.status, basicGroup.status)) {
				return false;
			}
			if (this.isActive != basicGroup.isActive) {
				return false;
			}
			if (this.upgradedToSupergroupId != basicGroup.upgradedToSupergroupId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.id);
			result = result * 31 + (this.status == null ? 0 : this.status.hashCode());
			return result;
		}
	}

	/**
	 * Contains full information about a basic group.
	**/
	public static final class BasicGroupFullInfo extends Object {


		/**
		 * Chat photo; may be null if empty or unknown. If non-null, then it is the same photo as in chat.photo.
		**/
		public ChatPhoto photo;

		/**
		 * Group description. Updated only after the basic group is opened.
		**/
		public String description;

		/**
		 * User identifier of the creator of the group; 0 if unknown.
		**/
		public long creatorUserId;

		/**
		 * Group members.
		**/
		public ChatMember[] members;

		/**
		 * True, if non-administrators and non-bots can be hidden in responses to getSupergroupMembers and searchChatMembers for non-administrators after upgrading the basic group to a supergroup.
		**/
		public boolean canHideMembers;

		/**
		 * True, if aggressive anti-spam checks can be enabled or disabled in the supergroup after upgrading the basic group to a supergroup.
		**/
		public boolean canToggleAggressiveAntiSpam;

		/**
		 * Primary invite link for this group; may be null. For chat administrators with canInviteUsers right only. Updated only after the basic group is opened.
		**/
		public ChatInviteLink inviteLink;

		/**
		 * List of commands of bots in the group.
		**/
		public BotCommands[] botCommands;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1879035520;

		/**
		 * Contains full information about a basic group.
		**/
		public BasicGroupFullInfo() {}

		/**
		 * Contains full information about a basic group.
		 *
		 * @param photo Chat photo; may be null if empty or unknown. If non-null, then it is the same photo as in chat.photo.
		 * @param description Group description. Updated only after the basic group is opened.
		 * @param creatorUserId User identifier of the creator of the group; 0 if unknown.
		 * @param members Group members.
		 * @param canHideMembers True, if non-administrators and non-bots can be hidden in responses to getSupergroupMembers and searchChatMembers for non-administrators after upgrading the basic group to a supergroup.
		 * @param canToggleAggressiveAntiSpam True, if aggressive anti-spam checks can be enabled or disabled in the supergroup after upgrading the basic group to a supergroup.
		 * @param inviteLink Primary invite link for this group; may be null. For chat administrators with canInviteUsers right only. Updated only after the basic group is opened.
		 * @param botCommands List of commands of bots in the group.
		**/
		public BasicGroupFullInfo(ChatPhoto photo,
				String description,
				long creatorUserId,
				ChatMember[] members,
				boolean canHideMembers,
				boolean canToggleAggressiveAntiSpam,
				ChatInviteLink inviteLink,
				BotCommands[] botCommands) {
			this.photo = photo;
			this.description = description;
			this.creatorUserId = creatorUserId;
			this.members = members;
			this.canHideMembers = canHideMembers;
			this.canToggleAggressiveAntiSpam = canToggleAggressiveAntiSpam;
			this.inviteLink = inviteLink;
			this.botCommands = botCommands;
		}

		/**
		 * Contains full information about a basic group.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public BasicGroupFullInfo(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (ChatPhoto.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.photo = new ChatPhoto(input);
			}
			if (input.readBoolean()) {
				byte[] descriptionTmp = new byte[input.readInt()];
				input.readFully(descriptionTmp);
				this.description = new String(descriptionTmp, StandardCharsets.UTF_8);
			}
			this.creatorUserId = input.readLong();
			if (input.readBoolean()) {
				this.members = new ChatMember[input.readInt()];
				for (int i = 0; i < this.members.length; i++) {
					if (ChatMember.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.members[i] = new ChatMember(input);
				}
			}
			this.canHideMembers = input.readBoolean();
			this.canToggleAggressiveAntiSpam = input.readBoolean();
			if (input.readBoolean()) {
				if (ChatInviteLink.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.inviteLink = new ChatInviteLink(input);
			}
			if (input.readBoolean()) {
				this.botCommands = new BotCommands[input.readInt()];
				for (int i = 0; i < this.botCommands.length; i++) {
					if (BotCommands.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.botCommands[i] = new BotCommands(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return BasicGroupFullInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(BasicGroupFullInfo.CONSTRUCTOR);
			if (this.photo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.photo.serialize(output);
			}
			if (this.description == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] descriptionTmp = this.description.getBytes(StandardCharsets.UTF_8);
				output.writeInt(descriptionTmp.length);
				output.write(descriptionTmp);
			}
			output.writeLong(this.creatorUserId);
			if (this.members == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.members.length);
				for (int i = 0; i < this.members.length; i++) {
					this.members[i].serialize(output);
				}
			}
			output.writeBoolean(this.canHideMembers);
			output.writeBoolean(this.canToggleAggressiveAntiSpam);
			if (this.inviteLink == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.inviteLink.serialize(output);
			}
			if (this.botCommands == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.botCommands.length);
				for (int i = 0; i < this.botCommands.length; i++) {
					this.botCommands[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			BasicGroupFullInfo basicGroupFullInfo = (BasicGroupFullInfo) o;
			if (!Objects.equals(this.photo, basicGroupFullInfo.photo)) {
				return false;
			}
			if (this.description != basicGroupFullInfo.description) {
				return false;
			}
			if (this.creatorUserId != basicGroupFullInfo.creatorUserId) {
				return false;
			}
			if (!Arrays.equals(this.members, basicGroupFullInfo.members)) {
				return false;
			}
			if (this.canHideMembers != basicGroupFullInfo.canHideMembers) {
				return false;
			}
			if (this.canToggleAggressiveAntiSpam != basicGroupFullInfo.canToggleAggressiveAntiSpam) {
				return false;
			}
			if (!Objects.equals(this.inviteLink, basicGroupFullInfo.inviteLink)) {
				return false;
			}
			if (!Arrays.equals(this.botCommands, basicGroupFullInfo.botCommands)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.creatorUserId);
			result = result * 31 + (this.photo == null ? 0 : this.photo.hashCode());
			result = result * 31 + (this.description == null ? 0 : this.description.hashCode());
			result = result * 31 + (Arrays.hashCode(this.members));
			result = result * 31 + (this.inviteLink == null ? 0 : this.inviteLink.hashCode());
			result = result * 31 + (Arrays.hashCode(this.botCommands));
			return result;
		}
	}

	/**
	 * Represents a command supported by a bot.
	**/
	public static final class BotCommand extends Object {


		/**
		 * Text of the bot command.
		**/
		public String command;

		/**
		 * Description of the bot command.
		**/
		public String description;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1032140601;

		/**
		 * Represents a command supported by a bot.
		**/
		public BotCommand() {}

		/**
		 * Represents a command supported by a bot.
		 *
		 * @param command Text of the bot command.
		 * @param description Description of the bot command.
		**/
		public BotCommand(String command, String description) {
			this.command = command;
			this.description = description;
		}

		/**
		 * Represents a command supported by a bot.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public BotCommand(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] commandTmp = new byte[input.readInt()];
				input.readFully(commandTmp);
				this.command = new String(commandTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] descriptionTmp = new byte[input.readInt()];
				input.readFully(descriptionTmp);
				this.description = new String(descriptionTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return BotCommand.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(BotCommand.CONSTRUCTOR);
			if (this.command == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] commandTmp = this.command.getBytes(StandardCharsets.UTF_8);
				output.writeInt(commandTmp.length);
				output.write(commandTmp);
			}
			if (this.description == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] descriptionTmp = this.description.getBytes(StandardCharsets.UTF_8);
				output.writeInt(descriptionTmp.length);
				output.write(descriptionTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			BotCommand botCommand = (BotCommand) o;
			if (this.command != botCommand.command) {
				return false;
			}
			if (this.description != botCommand.description) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.command == null ? 0 : this.command.hashCode();
			result = result * 31 + (this.description == null ? 0 : this.description.hashCode());
			return result;
		}
	}

	/**
	 * A scope covering all users.
	**/
	public static final class BotCommandScopeDefault extends BotCommandScope {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 795652779;

		/**
		 * A scope covering all users.
		**/
		public BotCommandScopeDefault() {}

		/**
		 * A scope covering all users.
		 *
		**/

		/**
		 * A scope covering all users.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public BotCommandScopeDefault(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return BotCommandScopeDefault.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(BotCommandScopeDefault.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return BotCommandScopeDefault.CONSTRUCTOR;
		}
	}

	/**
	 * A scope covering all private chats.
	**/
	public static final class BotCommandScopeAllPrivateChats extends BotCommandScope {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -344889543;

		/**
		 * A scope covering all private chats.
		**/
		public BotCommandScopeAllPrivateChats() {}

		/**
		 * A scope covering all private chats.
		 *
		**/

		/**
		 * A scope covering all private chats.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public BotCommandScopeAllPrivateChats(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return BotCommandScopeAllPrivateChats.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(BotCommandScopeAllPrivateChats.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return BotCommandScopeAllPrivateChats.CONSTRUCTOR;
		}
	}

	/**
	 * A scope covering all group and supergroup chats.
	**/
	public static final class BotCommandScopeAllGroupChats extends BotCommandScope {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -981088162;

		/**
		 * A scope covering all group and supergroup chats.
		**/
		public BotCommandScopeAllGroupChats() {}

		/**
		 * A scope covering all group and supergroup chats.
		 *
		**/

		/**
		 * A scope covering all group and supergroup chats.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public BotCommandScopeAllGroupChats(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return BotCommandScopeAllGroupChats.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(BotCommandScopeAllGroupChats.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return BotCommandScopeAllGroupChats.CONSTRUCTOR;
		}
	}

	/**
	 * A scope covering all group and supergroup chat administrators.
	**/
	public static final class BotCommandScopeAllChatAdministrators extends BotCommandScope {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1998329169;

		/**
		 * A scope covering all group and supergroup chat administrators.
		**/
		public BotCommandScopeAllChatAdministrators() {}

		/**
		 * A scope covering all group and supergroup chat administrators.
		 *
		**/

		/**
		 * A scope covering all group and supergroup chat administrators.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public BotCommandScopeAllChatAdministrators(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return BotCommandScopeAllChatAdministrators.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(BotCommandScopeAllChatAdministrators.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return BotCommandScopeAllChatAdministrators.CONSTRUCTOR;
		}
	}

	/**
	 * A scope covering all members of a chat.
	**/
	public static final class BotCommandScopeChat extends BotCommandScope {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -430234971;

		/**
		 * A scope covering all members of a chat.
		**/
		public BotCommandScopeChat() {}

		/**
		 * A scope covering all members of a chat.
		 *
		 * @param chatId Chat identifier.
		**/
		public BotCommandScopeChat(long chatId) {
			this.chatId = chatId;
		}

		/**
		 * A scope covering all members of a chat.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public BotCommandScopeChat(DataInput input) throws IOException {
			this.chatId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return BotCommandScopeChat.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(BotCommandScopeChat.CONSTRUCTOR);
			output.writeLong(this.chatId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			BotCommandScopeChat botCommandScopeChat = (BotCommandScopeChat) o;
			if (this.chatId != botCommandScopeChat.chatId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.chatId);
		}
	}

	/**
	 * A scope covering all administrators of a chat.
	**/
	public static final class BotCommandScopeChatAdministrators extends BotCommandScope {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1119682126;

		/**
		 * A scope covering all administrators of a chat.
		**/
		public BotCommandScopeChatAdministrators() {}

		/**
		 * A scope covering all administrators of a chat.
		 *
		 * @param chatId Chat identifier.
		**/
		public BotCommandScopeChatAdministrators(long chatId) {
			this.chatId = chatId;
		}

		/**
		 * A scope covering all administrators of a chat.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public BotCommandScopeChatAdministrators(DataInput input) throws IOException {
			this.chatId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return BotCommandScopeChatAdministrators.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(BotCommandScopeChatAdministrators.CONSTRUCTOR);
			output.writeLong(this.chatId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			BotCommandScopeChatAdministrators botCommandScopeChatAdministrators = (BotCommandScopeChatAdministrators) o;
			if (this.chatId != botCommandScopeChatAdministrators.chatId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.chatId);
		}
	}

	/**
	 * A scope covering a member of a chat.
	**/
	public static final class BotCommandScopeChatMember extends BotCommandScope {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * User identifier.
		**/
		public long userId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -211380494;

		/**
		 * A scope covering a member of a chat.
		**/
		public BotCommandScopeChatMember() {}

		/**
		 * A scope covering a member of a chat.
		 *
		 * @param chatId Chat identifier.
		 * @param userId User identifier.
		**/
		public BotCommandScopeChatMember(long chatId, long userId) {
			this.chatId = chatId;
			this.userId = userId;
		}

		/**
		 * A scope covering a member of a chat.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public BotCommandScopeChatMember(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.userId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return BotCommandScopeChatMember.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(BotCommandScopeChatMember.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.userId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			BotCommandScopeChatMember botCommandScopeChatMember = (BotCommandScopeChatMember) o;
			if (this.chatId != botCommandScopeChatMember.chatId) {
				return false;
			}
			if (this.userId != botCommandScopeChatMember.userId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Contains a list of bot commands.
	**/
	public static final class BotCommands extends Object {


		/**
		 * Bot&#039;s user identifier.
		**/
		public long botUserId;

		/**
		 * List of bot commands.
		**/
		public BotCommand[] commands;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1741364468;

		/**
		 * Contains a list of bot commands.
		**/
		public BotCommands() {}

		/**
		 * Contains a list of bot commands.
		 *
		 * @param botUserId Bot&#039;s user identifier.
		 * @param commands List of bot commands.
		**/
		public BotCommands(long botUserId, BotCommand[] commands) {
			this.botUserId = botUserId;
			this.commands = commands;
		}

		/**
		 * Contains a list of bot commands.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public BotCommands(DataInput input) throws IOException {
			this.botUserId = input.readLong();
			if (input.readBoolean()) {
				this.commands = new BotCommand[input.readInt()];
				for (int i = 0; i < this.commands.length; i++) {
					if (BotCommand.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.commands[i] = new BotCommand(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return BotCommands.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(BotCommands.CONSTRUCTOR);
			output.writeLong(this.botUserId);
			if (this.commands == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.commands.length);
				for (int i = 0; i < this.commands.length; i++) {
					this.commands[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			BotCommands botCommands = (BotCommands) o;
			if (this.botUserId != botCommands.botUserId) {
				return false;
			}
			if (!Arrays.equals(this.commands, botCommands.commands)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.botUserId);
			result = result * 31 + (Arrays.hashCode(this.commands));
			return result;
		}
	}

	/**
	 * Contains information about a bot.
	**/
	public static final class BotInfo extends Object {


		/**
		 * The text that is shown on the bot&#039;s profile page and is sent together with the link when users share the bot.
		**/
		public String shortDescription;

		/**
		 * The text shown in the chat with the bot if the chat is empty.
		**/
		public String description;

		/**
		 * Photo shown in the chat with the bot if the chat is empty; may be null.
		**/
		public Photo photo;

		/**
		 * Animation shown in the chat with the bot if the chat is empty; may be null.
		**/
		public Animation animation;

		/**
		 * Information about a button to show instead of the bot commands menu button; may be null if ordinary bot commands menu must be shown.
		**/
		public BotMenuButton menuButton;

		/**
		 * List of the bot commands.
		**/
		public BotCommand[] commands;

		/**
		 * Default administrator rights for adding the bot to basic group and supergroup chats; may be null.
		**/
		public ChatAdministratorRights defaultGroupAdministratorRights;

		/**
		 * Default administrator rights for adding the bot to channels; may be null.
		**/
		public ChatAdministratorRights defaultChannelAdministratorRights;

		/**
		 * The internal link, which can be used to edit bot commands; may be null.
		**/
		public InternalLinkType editCommandsLink;

		/**
		 * The internal link, which can be used to edit bot description; may be null.
		**/
		public InternalLinkType editDescriptionLink;

		/**
		 * The internal link, which can be used to edit the photo or animation shown in the chat with the bot if the chat is empty; may be null.
		**/
		public InternalLinkType editDescriptionMediaLink;

		/**
		 * The internal link, which can be used to edit bot settings; may be null.
		**/
		public InternalLinkType editSettingsLink;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1472546735;

		/**
		 * Contains information about a bot.
		**/
		public BotInfo() {}

		/**
		 * Contains information about a bot.
		 *
		 * @param shortDescription The text that is shown on the bot&#039;s profile page and is sent together with the link when users share the bot.
		 * @param description The text shown in the chat with the bot if the chat is empty.
		 * @param photo Photo shown in the chat with the bot if the chat is empty; may be null.
		 * @param animation Animation shown in the chat with the bot if the chat is empty; may be null.
		 * @param menuButton Information about a button to show instead of the bot commands menu button; may be null if ordinary bot commands menu must be shown.
		 * @param commands List of the bot commands.
		 * @param defaultGroupAdministratorRights Default administrator rights for adding the bot to basic group and supergroup chats; may be null.
		 * @param defaultChannelAdministratorRights Default administrator rights for adding the bot to channels; may be null.
		 * @param editCommandsLink The internal link, which can be used to edit bot commands; may be null.
		 * @param editDescriptionLink The internal link, which can be used to edit bot description; may be null.
		 * @param editDescriptionMediaLink The internal link, which can be used to edit the photo or animation shown in the chat with the bot if the chat is empty; may be null.
		 * @param editSettingsLink The internal link, which can be used to edit bot settings; may be null.
		**/
		public BotInfo(String shortDescription,
				String description,
				Photo photo,
				Animation animation,
				BotMenuButton menuButton,
				BotCommand[] commands,
				ChatAdministratorRights defaultGroupAdministratorRights,
				ChatAdministratorRights defaultChannelAdministratorRights,
				InternalLinkType editCommandsLink,
				InternalLinkType editDescriptionLink,
				InternalLinkType editDescriptionMediaLink,
				InternalLinkType editSettingsLink) {
			this.shortDescription = shortDescription;
			this.description = description;
			this.photo = photo;
			this.animation = animation;
			this.menuButton = menuButton;
			this.commands = commands;
			this.defaultGroupAdministratorRights = defaultGroupAdministratorRights;
			this.defaultChannelAdministratorRights = defaultChannelAdministratorRights;
			this.editCommandsLink = editCommandsLink;
			this.editDescriptionLink = editDescriptionLink;
			this.editDescriptionMediaLink = editDescriptionMediaLink;
			this.editSettingsLink = editSettingsLink;
		}

		/**
		 * Contains information about a bot.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public BotInfo(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] shortDescriptionTmp = new byte[input.readInt()];
				input.readFully(shortDescriptionTmp);
				this.shortDescription = new String(shortDescriptionTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] descriptionTmp = new byte[input.readInt()];
				input.readFully(descriptionTmp);
				this.description = new String(descriptionTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (Photo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.photo = new Photo(input);
			}
			if (input.readBoolean()) {
				if (Animation.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.animation = new Animation(input);
			}
			if (input.readBoolean()) {
				if (BotMenuButton.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.menuButton = new BotMenuButton(input);
			}
			if (input.readBoolean()) {
				this.commands = new BotCommand[input.readInt()];
				for (int i = 0; i < this.commands.length; i++) {
					if (BotCommand.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.commands[i] = new BotCommand(input);
				}
			}
			if (input.readBoolean()) {
				if (ChatAdministratorRights.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.defaultGroupAdministratorRights = new ChatAdministratorRights(input);
			}
			if (input.readBoolean()) {
				if (ChatAdministratorRights.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.defaultChannelAdministratorRights = new ChatAdministratorRights(input);
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InternalLinkTypeActiveSessions.CONSTRUCTOR: this.editCommandsLink = new InternalLinkTypeActiveSessions(input); break;
					case InternalLinkTypeAttachmentMenuBot.CONSTRUCTOR: this.editCommandsLink = new InternalLinkTypeAttachmentMenuBot(input); break;
					case InternalLinkTypeAuthenticationCode.CONSTRUCTOR: this.editCommandsLink = new InternalLinkTypeAuthenticationCode(input); break;
					case InternalLinkTypeBackground.CONSTRUCTOR: this.editCommandsLink = new InternalLinkTypeBackground(input); break;
					case InternalLinkTypeBotAddToChannel.CONSTRUCTOR: this.editCommandsLink = new InternalLinkTypeBotAddToChannel(input); break;
					case InternalLinkTypeBotStart.CONSTRUCTOR: this.editCommandsLink = new InternalLinkTypeBotStart(input); break;
					case InternalLinkTypeBotStartInGroup.CONSTRUCTOR: this.editCommandsLink = new InternalLinkTypeBotStartInGroup(input); break;
					case InternalLinkTypeChangePhoneNumber.CONSTRUCTOR: this.editCommandsLink = new InternalLinkTypeChangePhoneNumber(input); break;
					case InternalLinkTypeChatFolderInvite.CONSTRUCTOR: this.editCommandsLink = new InternalLinkTypeChatFolderInvite(input); break;
					case InternalLinkTypeChatFolderSettings.CONSTRUCTOR: this.editCommandsLink = new InternalLinkTypeChatFolderSettings(input); break;
					case InternalLinkTypeChatInvite.CONSTRUCTOR: this.editCommandsLink = new InternalLinkTypeChatInvite(input); break;
					case InternalLinkTypeDefaultMessageAutoDeleteTimerSettings.CONSTRUCTOR: this.editCommandsLink = new InternalLinkTypeDefaultMessageAutoDeleteTimerSettings(input); break;
					case InternalLinkTypeEditProfileSettings.CONSTRUCTOR: this.editCommandsLink = new InternalLinkTypeEditProfileSettings(input); break;
					case InternalLinkTypeGame.CONSTRUCTOR: this.editCommandsLink = new InternalLinkTypeGame(input); break;
					case InternalLinkTypeInstantView.CONSTRUCTOR: this.editCommandsLink = new InternalLinkTypeInstantView(input); break;
					case InternalLinkTypeInvoice.CONSTRUCTOR: this.editCommandsLink = new InternalLinkTypeInvoice(input); break;
					case InternalLinkTypeLanguagePack.CONSTRUCTOR: this.editCommandsLink = new InternalLinkTypeLanguagePack(input); break;
					case InternalLinkTypeLanguageSettings.CONSTRUCTOR: this.editCommandsLink = new InternalLinkTypeLanguageSettings(input); break;
					case InternalLinkTypeMessage.CONSTRUCTOR: this.editCommandsLink = new InternalLinkTypeMessage(input); break;
					case InternalLinkTypeMessageDraft.CONSTRUCTOR: this.editCommandsLink = new InternalLinkTypeMessageDraft(input); break;
					case InternalLinkTypePassportDataRequest.CONSTRUCTOR: this.editCommandsLink = new InternalLinkTypePassportDataRequest(input); break;
					case InternalLinkTypePhoneNumberConfirmation.CONSTRUCTOR: this.editCommandsLink = new InternalLinkTypePhoneNumberConfirmation(input); break;
					case InternalLinkTypePremiumFeatures.CONSTRUCTOR: this.editCommandsLink = new InternalLinkTypePremiumFeatures(input); break;
					case InternalLinkTypePrivacyAndSecuritySettings.CONSTRUCTOR: this.editCommandsLink = new InternalLinkTypePrivacyAndSecuritySettings(input); break;
					case InternalLinkTypeProxy.CONSTRUCTOR: this.editCommandsLink = new InternalLinkTypeProxy(input); break;
					case InternalLinkTypePublicChat.CONSTRUCTOR: this.editCommandsLink = new InternalLinkTypePublicChat(input); break;
					case InternalLinkTypeQrCodeAuthentication.CONSTRUCTOR: this.editCommandsLink = new InternalLinkTypeQrCodeAuthentication(input); break;
					case InternalLinkTypeRestorePurchases.CONSTRUCTOR: this.editCommandsLink = new InternalLinkTypeRestorePurchases(input); break;
					case InternalLinkTypeSettings.CONSTRUCTOR: this.editCommandsLink = new InternalLinkTypeSettings(input); break;
					case InternalLinkTypeStickerSet.CONSTRUCTOR: this.editCommandsLink = new InternalLinkTypeStickerSet(input); break;
					case InternalLinkTypeTheme.CONSTRUCTOR: this.editCommandsLink = new InternalLinkTypeTheme(input); break;
					case InternalLinkTypeThemeSettings.CONSTRUCTOR: this.editCommandsLink = new InternalLinkTypeThemeSettings(input); break;
					case InternalLinkTypeUnknownDeepLink.CONSTRUCTOR: this.editCommandsLink = new InternalLinkTypeUnknownDeepLink(input); break;
					case InternalLinkTypeUnsupportedProxy.CONSTRUCTOR: this.editCommandsLink = new InternalLinkTypeUnsupportedProxy(input); break;
					case InternalLinkTypeUserPhoneNumber.CONSTRUCTOR: this.editCommandsLink = new InternalLinkTypeUserPhoneNumber(input); break;
					case InternalLinkTypeUserToken.CONSTRUCTOR: this.editCommandsLink = new InternalLinkTypeUserToken(input); break;
					case InternalLinkTypeVideoChat.CONSTRUCTOR: this.editCommandsLink = new InternalLinkTypeVideoChat(input); break;
					case InternalLinkTypeWebApp.CONSTRUCTOR: this.editCommandsLink = new InternalLinkTypeWebApp(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InternalLinkTypeActiveSessions.CONSTRUCTOR: this.editDescriptionLink = new InternalLinkTypeActiveSessions(input); break;
					case InternalLinkTypeAttachmentMenuBot.CONSTRUCTOR: this.editDescriptionLink = new InternalLinkTypeAttachmentMenuBot(input); break;
					case InternalLinkTypeAuthenticationCode.CONSTRUCTOR: this.editDescriptionLink = new InternalLinkTypeAuthenticationCode(input); break;
					case InternalLinkTypeBackground.CONSTRUCTOR: this.editDescriptionLink = new InternalLinkTypeBackground(input); break;
					case InternalLinkTypeBotAddToChannel.CONSTRUCTOR: this.editDescriptionLink = new InternalLinkTypeBotAddToChannel(input); break;
					case InternalLinkTypeBotStart.CONSTRUCTOR: this.editDescriptionLink = new InternalLinkTypeBotStart(input); break;
					case InternalLinkTypeBotStartInGroup.CONSTRUCTOR: this.editDescriptionLink = new InternalLinkTypeBotStartInGroup(input); break;
					case InternalLinkTypeChangePhoneNumber.CONSTRUCTOR: this.editDescriptionLink = new InternalLinkTypeChangePhoneNumber(input); break;
					case InternalLinkTypeChatFolderInvite.CONSTRUCTOR: this.editDescriptionLink = new InternalLinkTypeChatFolderInvite(input); break;
					case InternalLinkTypeChatFolderSettings.CONSTRUCTOR: this.editDescriptionLink = new InternalLinkTypeChatFolderSettings(input); break;
					case InternalLinkTypeChatInvite.CONSTRUCTOR: this.editDescriptionLink = new InternalLinkTypeChatInvite(input); break;
					case InternalLinkTypeDefaultMessageAutoDeleteTimerSettings.CONSTRUCTOR: this.editDescriptionLink = new InternalLinkTypeDefaultMessageAutoDeleteTimerSettings(input); break;
					case InternalLinkTypeEditProfileSettings.CONSTRUCTOR: this.editDescriptionLink = new InternalLinkTypeEditProfileSettings(input); break;
					case InternalLinkTypeGame.CONSTRUCTOR: this.editDescriptionLink = new InternalLinkTypeGame(input); break;
					case InternalLinkTypeInstantView.CONSTRUCTOR: this.editDescriptionLink = new InternalLinkTypeInstantView(input); break;
					case InternalLinkTypeInvoice.CONSTRUCTOR: this.editDescriptionLink = new InternalLinkTypeInvoice(input); break;
					case InternalLinkTypeLanguagePack.CONSTRUCTOR: this.editDescriptionLink = new InternalLinkTypeLanguagePack(input); break;
					case InternalLinkTypeLanguageSettings.CONSTRUCTOR: this.editDescriptionLink = new InternalLinkTypeLanguageSettings(input); break;
					case InternalLinkTypeMessage.CONSTRUCTOR: this.editDescriptionLink = new InternalLinkTypeMessage(input); break;
					case InternalLinkTypeMessageDraft.CONSTRUCTOR: this.editDescriptionLink = new InternalLinkTypeMessageDraft(input); break;
					case InternalLinkTypePassportDataRequest.CONSTRUCTOR: this.editDescriptionLink = new InternalLinkTypePassportDataRequest(input); break;
					case InternalLinkTypePhoneNumberConfirmation.CONSTRUCTOR: this.editDescriptionLink = new InternalLinkTypePhoneNumberConfirmation(input); break;
					case InternalLinkTypePremiumFeatures.CONSTRUCTOR: this.editDescriptionLink = new InternalLinkTypePremiumFeatures(input); break;
					case InternalLinkTypePrivacyAndSecuritySettings.CONSTRUCTOR: this.editDescriptionLink = new InternalLinkTypePrivacyAndSecuritySettings(input); break;
					case InternalLinkTypeProxy.CONSTRUCTOR: this.editDescriptionLink = new InternalLinkTypeProxy(input); break;
					case InternalLinkTypePublicChat.CONSTRUCTOR: this.editDescriptionLink = new InternalLinkTypePublicChat(input); break;
					case InternalLinkTypeQrCodeAuthentication.CONSTRUCTOR: this.editDescriptionLink = new InternalLinkTypeQrCodeAuthentication(input); break;
					case InternalLinkTypeRestorePurchases.CONSTRUCTOR: this.editDescriptionLink = new InternalLinkTypeRestorePurchases(input); break;
					case InternalLinkTypeSettings.CONSTRUCTOR: this.editDescriptionLink = new InternalLinkTypeSettings(input); break;
					case InternalLinkTypeStickerSet.CONSTRUCTOR: this.editDescriptionLink = new InternalLinkTypeStickerSet(input); break;
					case InternalLinkTypeTheme.CONSTRUCTOR: this.editDescriptionLink = new InternalLinkTypeTheme(input); break;
					case InternalLinkTypeThemeSettings.CONSTRUCTOR: this.editDescriptionLink = new InternalLinkTypeThemeSettings(input); break;
					case InternalLinkTypeUnknownDeepLink.CONSTRUCTOR: this.editDescriptionLink = new InternalLinkTypeUnknownDeepLink(input); break;
					case InternalLinkTypeUnsupportedProxy.CONSTRUCTOR: this.editDescriptionLink = new InternalLinkTypeUnsupportedProxy(input); break;
					case InternalLinkTypeUserPhoneNumber.CONSTRUCTOR: this.editDescriptionLink = new InternalLinkTypeUserPhoneNumber(input); break;
					case InternalLinkTypeUserToken.CONSTRUCTOR: this.editDescriptionLink = new InternalLinkTypeUserToken(input); break;
					case InternalLinkTypeVideoChat.CONSTRUCTOR: this.editDescriptionLink = new InternalLinkTypeVideoChat(input); break;
					case InternalLinkTypeWebApp.CONSTRUCTOR: this.editDescriptionLink = new InternalLinkTypeWebApp(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InternalLinkTypeActiveSessions.CONSTRUCTOR: this.editDescriptionMediaLink = new InternalLinkTypeActiveSessions(input); break;
					case InternalLinkTypeAttachmentMenuBot.CONSTRUCTOR: this.editDescriptionMediaLink = new InternalLinkTypeAttachmentMenuBot(input); break;
					case InternalLinkTypeAuthenticationCode.CONSTRUCTOR: this.editDescriptionMediaLink = new InternalLinkTypeAuthenticationCode(input); break;
					case InternalLinkTypeBackground.CONSTRUCTOR: this.editDescriptionMediaLink = new InternalLinkTypeBackground(input); break;
					case InternalLinkTypeBotAddToChannel.CONSTRUCTOR: this.editDescriptionMediaLink = new InternalLinkTypeBotAddToChannel(input); break;
					case InternalLinkTypeBotStart.CONSTRUCTOR: this.editDescriptionMediaLink = new InternalLinkTypeBotStart(input); break;
					case InternalLinkTypeBotStartInGroup.CONSTRUCTOR: this.editDescriptionMediaLink = new InternalLinkTypeBotStartInGroup(input); break;
					case InternalLinkTypeChangePhoneNumber.CONSTRUCTOR: this.editDescriptionMediaLink = new InternalLinkTypeChangePhoneNumber(input); break;
					case InternalLinkTypeChatFolderInvite.CONSTRUCTOR: this.editDescriptionMediaLink = new InternalLinkTypeChatFolderInvite(input); break;
					case InternalLinkTypeChatFolderSettings.CONSTRUCTOR: this.editDescriptionMediaLink = new InternalLinkTypeChatFolderSettings(input); break;
					case InternalLinkTypeChatInvite.CONSTRUCTOR: this.editDescriptionMediaLink = new InternalLinkTypeChatInvite(input); break;
					case InternalLinkTypeDefaultMessageAutoDeleteTimerSettings.CONSTRUCTOR: this.editDescriptionMediaLink = new InternalLinkTypeDefaultMessageAutoDeleteTimerSettings(input); break;
					case InternalLinkTypeEditProfileSettings.CONSTRUCTOR: this.editDescriptionMediaLink = new InternalLinkTypeEditProfileSettings(input); break;
					case InternalLinkTypeGame.CONSTRUCTOR: this.editDescriptionMediaLink = new InternalLinkTypeGame(input); break;
					case InternalLinkTypeInstantView.CONSTRUCTOR: this.editDescriptionMediaLink = new InternalLinkTypeInstantView(input); break;
					case InternalLinkTypeInvoice.CONSTRUCTOR: this.editDescriptionMediaLink = new InternalLinkTypeInvoice(input); break;
					case InternalLinkTypeLanguagePack.CONSTRUCTOR: this.editDescriptionMediaLink = new InternalLinkTypeLanguagePack(input); break;
					case InternalLinkTypeLanguageSettings.CONSTRUCTOR: this.editDescriptionMediaLink = new InternalLinkTypeLanguageSettings(input); break;
					case InternalLinkTypeMessage.CONSTRUCTOR: this.editDescriptionMediaLink = new InternalLinkTypeMessage(input); break;
					case InternalLinkTypeMessageDraft.CONSTRUCTOR: this.editDescriptionMediaLink = new InternalLinkTypeMessageDraft(input); break;
					case InternalLinkTypePassportDataRequest.CONSTRUCTOR: this.editDescriptionMediaLink = new InternalLinkTypePassportDataRequest(input); break;
					case InternalLinkTypePhoneNumberConfirmation.CONSTRUCTOR: this.editDescriptionMediaLink = new InternalLinkTypePhoneNumberConfirmation(input); break;
					case InternalLinkTypePremiumFeatures.CONSTRUCTOR: this.editDescriptionMediaLink = new InternalLinkTypePremiumFeatures(input); break;
					case InternalLinkTypePrivacyAndSecuritySettings.CONSTRUCTOR: this.editDescriptionMediaLink = new InternalLinkTypePrivacyAndSecuritySettings(input); break;
					case InternalLinkTypeProxy.CONSTRUCTOR: this.editDescriptionMediaLink = new InternalLinkTypeProxy(input); break;
					case InternalLinkTypePublicChat.CONSTRUCTOR: this.editDescriptionMediaLink = new InternalLinkTypePublicChat(input); break;
					case InternalLinkTypeQrCodeAuthentication.CONSTRUCTOR: this.editDescriptionMediaLink = new InternalLinkTypeQrCodeAuthentication(input); break;
					case InternalLinkTypeRestorePurchases.CONSTRUCTOR: this.editDescriptionMediaLink = new InternalLinkTypeRestorePurchases(input); break;
					case InternalLinkTypeSettings.CONSTRUCTOR: this.editDescriptionMediaLink = new InternalLinkTypeSettings(input); break;
					case InternalLinkTypeStickerSet.CONSTRUCTOR: this.editDescriptionMediaLink = new InternalLinkTypeStickerSet(input); break;
					case InternalLinkTypeTheme.CONSTRUCTOR: this.editDescriptionMediaLink = new InternalLinkTypeTheme(input); break;
					case InternalLinkTypeThemeSettings.CONSTRUCTOR: this.editDescriptionMediaLink = new InternalLinkTypeThemeSettings(input); break;
					case InternalLinkTypeUnknownDeepLink.CONSTRUCTOR: this.editDescriptionMediaLink = new InternalLinkTypeUnknownDeepLink(input); break;
					case InternalLinkTypeUnsupportedProxy.CONSTRUCTOR: this.editDescriptionMediaLink = new InternalLinkTypeUnsupportedProxy(input); break;
					case InternalLinkTypeUserPhoneNumber.CONSTRUCTOR: this.editDescriptionMediaLink = new InternalLinkTypeUserPhoneNumber(input); break;
					case InternalLinkTypeUserToken.CONSTRUCTOR: this.editDescriptionMediaLink = new InternalLinkTypeUserToken(input); break;
					case InternalLinkTypeVideoChat.CONSTRUCTOR: this.editDescriptionMediaLink = new InternalLinkTypeVideoChat(input); break;
					case InternalLinkTypeWebApp.CONSTRUCTOR: this.editDescriptionMediaLink = new InternalLinkTypeWebApp(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InternalLinkTypeActiveSessions.CONSTRUCTOR: this.editSettingsLink = new InternalLinkTypeActiveSessions(input); break;
					case InternalLinkTypeAttachmentMenuBot.CONSTRUCTOR: this.editSettingsLink = new InternalLinkTypeAttachmentMenuBot(input); break;
					case InternalLinkTypeAuthenticationCode.CONSTRUCTOR: this.editSettingsLink = new InternalLinkTypeAuthenticationCode(input); break;
					case InternalLinkTypeBackground.CONSTRUCTOR: this.editSettingsLink = new InternalLinkTypeBackground(input); break;
					case InternalLinkTypeBotAddToChannel.CONSTRUCTOR: this.editSettingsLink = new InternalLinkTypeBotAddToChannel(input); break;
					case InternalLinkTypeBotStart.CONSTRUCTOR: this.editSettingsLink = new InternalLinkTypeBotStart(input); break;
					case InternalLinkTypeBotStartInGroup.CONSTRUCTOR: this.editSettingsLink = new InternalLinkTypeBotStartInGroup(input); break;
					case InternalLinkTypeChangePhoneNumber.CONSTRUCTOR: this.editSettingsLink = new InternalLinkTypeChangePhoneNumber(input); break;
					case InternalLinkTypeChatFolderInvite.CONSTRUCTOR: this.editSettingsLink = new InternalLinkTypeChatFolderInvite(input); break;
					case InternalLinkTypeChatFolderSettings.CONSTRUCTOR: this.editSettingsLink = new InternalLinkTypeChatFolderSettings(input); break;
					case InternalLinkTypeChatInvite.CONSTRUCTOR: this.editSettingsLink = new InternalLinkTypeChatInvite(input); break;
					case InternalLinkTypeDefaultMessageAutoDeleteTimerSettings.CONSTRUCTOR: this.editSettingsLink = new InternalLinkTypeDefaultMessageAutoDeleteTimerSettings(input); break;
					case InternalLinkTypeEditProfileSettings.CONSTRUCTOR: this.editSettingsLink = new InternalLinkTypeEditProfileSettings(input); break;
					case InternalLinkTypeGame.CONSTRUCTOR: this.editSettingsLink = new InternalLinkTypeGame(input); break;
					case InternalLinkTypeInstantView.CONSTRUCTOR: this.editSettingsLink = new InternalLinkTypeInstantView(input); break;
					case InternalLinkTypeInvoice.CONSTRUCTOR: this.editSettingsLink = new InternalLinkTypeInvoice(input); break;
					case InternalLinkTypeLanguagePack.CONSTRUCTOR: this.editSettingsLink = new InternalLinkTypeLanguagePack(input); break;
					case InternalLinkTypeLanguageSettings.CONSTRUCTOR: this.editSettingsLink = new InternalLinkTypeLanguageSettings(input); break;
					case InternalLinkTypeMessage.CONSTRUCTOR: this.editSettingsLink = new InternalLinkTypeMessage(input); break;
					case InternalLinkTypeMessageDraft.CONSTRUCTOR: this.editSettingsLink = new InternalLinkTypeMessageDraft(input); break;
					case InternalLinkTypePassportDataRequest.CONSTRUCTOR: this.editSettingsLink = new InternalLinkTypePassportDataRequest(input); break;
					case InternalLinkTypePhoneNumberConfirmation.CONSTRUCTOR: this.editSettingsLink = new InternalLinkTypePhoneNumberConfirmation(input); break;
					case InternalLinkTypePremiumFeatures.CONSTRUCTOR: this.editSettingsLink = new InternalLinkTypePremiumFeatures(input); break;
					case InternalLinkTypePrivacyAndSecuritySettings.CONSTRUCTOR: this.editSettingsLink = new InternalLinkTypePrivacyAndSecuritySettings(input); break;
					case InternalLinkTypeProxy.CONSTRUCTOR: this.editSettingsLink = new InternalLinkTypeProxy(input); break;
					case InternalLinkTypePublicChat.CONSTRUCTOR: this.editSettingsLink = new InternalLinkTypePublicChat(input); break;
					case InternalLinkTypeQrCodeAuthentication.CONSTRUCTOR: this.editSettingsLink = new InternalLinkTypeQrCodeAuthentication(input); break;
					case InternalLinkTypeRestorePurchases.CONSTRUCTOR: this.editSettingsLink = new InternalLinkTypeRestorePurchases(input); break;
					case InternalLinkTypeSettings.CONSTRUCTOR: this.editSettingsLink = new InternalLinkTypeSettings(input); break;
					case InternalLinkTypeStickerSet.CONSTRUCTOR: this.editSettingsLink = new InternalLinkTypeStickerSet(input); break;
					case InternalLinkTypeTheme.CONSTRUCTOR: this.editSettingsLink = new InternalLinkTypeTheme(input); break;
					case InternalLinkTypeThemeSettings.CONSTRUCTOR: this.editSettingsLink = new InternalLinkTypeThemeSettings(input); break;
					case InternalLinkTypeUnknownDeepLink.CONSTRUCTOR: this.editSettingsLink = new InternalLinkTypeUnknownDeepLink(input); break;
					case InternalLinkTypeUnsupportedProxy.CONSTRUCTOR: this.editSettingsLink = new InternalLinkTypeUnsupportedProxy(input); break;
					case InternalLinkTypeUserPhoneNumber.CONSTRUCTOR: this.editSettingsLink = new InternalLinkTypeUserPhoneNumber(input); break;
					case InternalLinkTypeUserToken.CONSTRUCTOR: this.editSettingsLink = new InternalLinkTypeUserToken(input); break;
					case InternalLinkTypeVideoChat.CONSTRUCTOR: this.editSettingsLink = new InternalLinkTypeVideoChat(input); break;
					case InternalLinkTypeWebApp.CONSTRUCTOR: this.editSettingsLink = new InternalLinkTypeWebApp(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return BotInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(BotInfo.CONSTRUCTOR);
			if (this.shortDescription == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] shortDescriptionTmp = this.shortDescription.getBytes(StandardCharsets.UTF_8);
				output.writeInt(shortDescriptionTmp.length);
				output.write(shortDescriptionTmp);
			}
			if (this.description == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] descriptionTmp = this.description.getBytes(StandardCharsets.UTF_8);
				output.writeInt(descriptionTmp.length);
				output.write(descriptionTmp);
			}
			if (this.photo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.photo.serialize(output);
			}
			if (this.animation == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.animation.serialize(output);
			}
			if (this.menuButton == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.menuButton.serialize(output);
			}
			if (this.commands == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.commands.length);
				for (int i = 0; i < this.commands.length; i++) {
					this.commands[i].serialize(output);
				}
			}
			if (this.defaultGroupAdministratorRights == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.defaultGroupAdministratorRights.serialize(output);
			}
			if (this.defaultChannelAdministratorRights == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.defaultChannelAdministratorRights.serialize(output);
			}
			if (this.editCommandsLink == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.editCommandsLink.serialize(output);
			}
			if (this.editDescriptionLink == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.editDescriptionLink.serialize(output);
			}
			if (this.editDescriptionMediaLink == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.editDescriptionMediaLink.serialize(output);
			}
			if (this.editSettingsLink == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.editSettingsLink.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			BotInfo botInfo = (BotInfo) o;
			if (this.shortDescription != botInfo.shortDescription) {
				return false;
			}
			if (this.description != botInfo.description) {
				return false;
			}
			if (!Objects.equals(this.photo, botInfo.photo)) {
				return false;
			}
			if (!Objects.equals(this.animation, botInfo.animation)) {
				return false;
			}
			if (!Objects.equals(this.menuButton, botInfo.menuButton)) {
				return false;
			}
			if (!Arrays.equals(this.commands, botInfo.commands)) {
				return false;
			}
			if (!Objects.equals(this.defaultGroupAdministratorRights, botInfo.defaultGroupAdministratorRights)) {
				return false;
			}
			if (!Objects.equals(this.defaultChannelAdministratorRights, botInfo.defaultChannelAdministratorRights)) {
				return false;
			}
			if (!Objects.equals(this.editCommandsLink, botInfo.editCommandsLink)) {
				return false;
			}
			if (!Objects.equals(this.editDescriptionLink, botInfo.editDescriptionLink)) {
				return false;
			}
			if (!Objects.equals(this.editDescriptionMediaLink, botInfo.editDescriptionMediaLink)) {
				return false;
			}
			if (!Objects.equals(this.editSettingsLink, botInfo.editSettingsLink)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.shortDescription == null ? 0 : this.shortDescription.hashCode();
			result = result * 31 + (this.description == null ? 0 : this.description.hashCode());
			result = result * 31 + (this.photo == null ? 0 : this.photo.hashCode());
			result = result * 31 + (this.animation == null ? 0 : this.animation.hashCode());
			result = result * 31 + (this.menuButton == null ? 0 : this.menuButton.hashCode());
			result = result * 31 + (Arrays.hashCode(this.commands));
			result = result * 31 + (this.defaultGroupAdministratorRights == null ? 0 : this.defaultGroupAdministratorRights.hashCode());
			result = result * 31 + (this.defaultChannelAdministratorRights == null ? 0 : this.defaultChannelAdministratorRights.hashCode());
			result = result * 31 + (this.editCommandsLink == null ? 0 : this.editCommandsLink.hashCode());
			result = result * 31 + (this.editDescriptionLink == null ? 0 : this.editDescriptionLink.hashCode());
			result = result * 31 + (this.editDescriptionMediaLink == null ? 0 : this.editDescriptionMediaLink.hashCode());
			result = result * 31 + (this.editSettingsLink == null ? 0 : this.editSettingsLink.hashCode());
			return result;
		}
	}

	/**
	 * Describes a button to be shown instead of bot commands menu button.
	**/
	public static final class BotMenuButton extends Object {


		/**
		 * Text of the button.
		**/
		public String text;

		/**
		 * URL to be passed to openWebApp.
		**/
		public String url;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -944407322;

		/**
		 * Describes a button to be shown instead of bot commands menu button.
		**/
		public BotMenuButton() {}

		/**
		 * Describes a button to be shown instead of bot commands menu button.
		 *
		 * @param text Text of the button.
		 * @param url URL to be passed to openWebApp.
		**/
		public BotMenuButton(String text, String url) {
			this.text = text;
			this.url = url;
		}

		/**
		 * Describes a button to be shown instead of bot commands menu button.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public BotMenuButton(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] textTmp = new byte[input.readInt()];
				input.readFully(textTmp);
				this.text = new String(textTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] urlTmp = new byte[input.readInt()];
				input.readFully(urlTmp);
				this.url = new String(urlTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return BotMenuButton.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(BotMenuButton.CONSTRUCTOR);
			if (this.text == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] textTmp = this.text.getBytes(StandardCharsets.UTF_8);
				output.writeInt(textTmp.length);
				output.write(textTmp);
			}
			if (this.url == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] urlTmp = this.url.getBytes(StandardCharsets.UTF_8);
				output.writeInt(urlTmp.length);
				output.write(urlTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			BotMenuButton botMenuButton = (BotMenuButton) o;
			if (this.text != botMenuButton.text) {
				return false;
			}
			if (this.url != botMenuButton.url) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.text == null ? 0 : this.text.hashCode();
			result = result * 31 + (this.url == null ? 0 : this.url.hashCode());
			return result;
		}
	}

	/**
	 * Describes a call.
	**/
	public static final class Call extends Object {


		/**
		 * Call identifier, not persistent.
		**/
		public int id;

		/**
		 * Peer user identifier.
		**/
		public long userId;

		/**
		 * True, if the call is outgoing.
		**/
		public boolean isOutgoing;

		/**
		 * True, if the call is a video call.
		**/
		public boolean isVideo;

		/**
		 * Call state.
		**/
		public CallState state;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 920360804;

		/**
		 * Describes a call.
		**/
		public Call() {}

		/**
		 * Describes a call.
		 *
		 * @param id Call identifier, not persistent.
		 * @param userId Peer user identifier.
		 * @param isOutgoing True, if the call is outgoing.
		 * @param isVideo True, if the call is a video call.
		 * @param state Call state.
		**/
		public Call(int id,
				long userId,
				boolean isOutgoing,
				boolean isVideo,
				CallState state) {
			this.id = id;
			this.userId = userId;
			this.isOutgoing = isOutgoing;
			this.isVideo = isVideo;
			this.state = state;
		}

		/**
		 * Describes a call.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public Call(DataInput input) throws IOException {
			this.id = input.readInt();
			this.userId = input.readLong();
			this.isOutgoing = input.readBoolean();
			this.isVideo = input.readBoolean();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case CallStatePending.CONSTRUCTOR: this.state = new CallStatePending(input); break;
					case CallStateExchangingKeys.CONSTRUCTOR: this.state = new CallStateExchangingKeys(input); break;
					case CallStateReady.CONSTRUCTOR: this.state = new CallStateReady(input); break;
					case CallStateHangingUp.CONSTRUCTOR: this.state = new CallStateHangingUp(input); break;
					case CallStateDiscarded.CONSTRUCTOR: this.state = new CallStateDiscarded(input); break;
					case CallStateError.CONSTRUCTOR: this.state = new CallStateError(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return Call.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(Call.CONSTRUCTOR);
			output.writeInt(this.id);
			output.writeLong(this.userId);
			output.writeBoolean(this.isOutgoing);
			output.writeBoolean(this.isVideo);
			if (this.state == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.state.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			Call call = (Call) o;
			if (this.id != call.id) {
				return false;
			}
			if (this.userId != call.userId) {
				return false;
			}
			if (this.isOutgoing != call.isOutgoing) {
				return false;
			}
			if (this.isVideo != call.isVideo) {
				return false;
			}
			if (!Objects.equals(this.state, call.state)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.id);
			result = result * 31 + (this.state == null ? 0 : this.state.hashCode());
			return result;
		}
	}

	/**
	 * The call wasn&#039;t discarded, or the reason is unknown.
	**/
	public static final class CallDiscardReasonEmpty extends CallDiscardReason {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1258917949;

		/**
		 * The call wasn&#039;t discarded, or the reason is unknown.
		**/
		public CallDiscardReasonEmpty() {}

		/**
		 * The call wasn&#039;t discarded, or the reason is unknown.
		 *
		**/

		/**
		 * The call wasn&#039;t discarded, or the reason is unknown.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CallDiscardReasonEmpty(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CallDiscardReasonEmpty.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CallDiscardReasonEmpty.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return CallDiscardReasonEmpty.CONSTRUCTOR;
		}
	}

	/**
	 * The call was ended before the conversation started. It was canceled
	 * by the caller or missed by the other party.
	**/
	public static final class CallDiscardReasonMissed extends CallDiscardReason {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1680358012;

		/**
		 * The call was ended before the conversation started. It was canceled by the caller or missed by the other party.
		**/
		public CallDiscardReasonMissed() {}

		/**
		 * The call was ended before the conversation started. It was canceled by the caller or missed by the other party.
		 *
		**/

		/**
		 * The call was ended before the conversation started. It was canceled by the caller or missed by the other party.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CallDiscardReasonMissed(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CallDiscardReasonMissed.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CallDiscardReasonMissed.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return CallDiscardReasonMissed.CONSTRUCTOR;
		}
	}

	/**
	 * The call was ended before the conversation started. It was declined
	 * by the other party.
	**/
	public static final class CallDiscardReasonDeclined extends CallDiscardReason {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1729926094;

		/**
		 * The call was ended before the conversation started. It was declined by the other party.
		**/
		public CallDiscardReasonDeclined() {}

		/**
		 * The call was ended before the conversation started. It was declined by the other party.
		 *
		**/

		/**
		 * The call was ended before the conversation started. It was declined by the other party.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CallDiscardReasonDeclined(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CallDiscardReasonDeclined.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CallDiscardReasonDeclined.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return CallDiscardReasonDeclined.CONSTRUCTOR;
		}
	}

	/**
	 * The call was ended during the conversation because the users were
	 * disconnected.
	**/
	public static final class CallDiscardReasonDisconnected extends CallDiscardReason {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1342872670;

		/**
		 * The call was ended during the conversation because the users were disconnected.
		**/
		public CallDiscardReasonDisconnected() {}

		/**
		 * The call was ended during the conversation because the users were disconnected.
		 *
		**/

		/**
		 * The call was ended during the conversation because the users were disconnected.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CallDiscardReasonDisconnected(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CallDiscardReasonDisconnected.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CallDiscardReasonDisconnected.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return CallDiscardReasonDisconnected.CONSTRUCTOR;
		}
	}

	/**
	 * The call was ended because one of the parties hung up.
	**/
	public static final class CallDiscardReasonHungUp extends CallDiscardReason {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 438216166;

		/**
		 * The call was ended because one of the parties hung up.
		**/
		public CallDiscardReasonHungUp() {}

		/**
		 * The call was ended because one of the parties hung up.
		 *
		**/

		/**
		 * The call was ended because one of the parties hung up.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CallDiscardReasonHungUp(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CallDiscardReasonHungUp.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CallDiscardReasonHungUp.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return CallDiscardReasonHungUp.CONSTRUCTOR;
		}
	}

	/**
	 * Contains the call identifier.
	**/
	public static final class CallId extends Object {


		/**
		 * Call identifier.
		**/
		public int id;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 65717769;

		/**
		 * Contains the call identifier.
		**/
		public CallId() {}

		/**
		 * Contains the call identifier.
		 *
		 * @param id Call identifier.
		**/
		public CallId(int id) {
			this.id = id;
		}

		/**
		 * Contains the call identifier.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CallId(DataInput input) throws IOException {
			this.id = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CallId.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CallId.CONSTRUCTOR);
			output.writeInt(this.id);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CallId callId = (CallId) o;
			if (this.id != callId.id) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.id);
		}
	}

	/**
	 * The user heard their own voice.
	**/
	public static final class CallProblemEcho extends CallProblem {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 801116548;

		/**
		 * The user heard their own voice.
		**/
		public CallProblemEcho() {}

		/**
		 * The user heard their own voice.
		 *
		**/

		/**
		 * The user heard their own voice.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CallProblemEcho(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CallProblemEcho.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CallProblemEcho.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return CallProblemEcho.CONSTRUCTOR;
		}
	}

	/**
	 * The user heard background noise.
	**/
	public static final class CallProblemNoise extends CallProblem {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1053065359;

		/**
		 * The user heard background noise.
		**/
		public CallProblemNoise() {}

		/**
		 * The user heard background noise.
		 *
		**/

		/**
		 * The user heard background noise.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CallProblemNoise(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CallProblemNoise.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CallProblemNoise.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return CallProblemNoise.CONSTRUCTOR;
		}
	}

	/**
	 * The other side kept disappearing.
	**/
	public static final class CallProblemInterruptions extends CallProblem {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1119493218;

		/**
		 * The other side kept disappearing.
		**/
		public CallProblemInterruptions() {}

		/**
		 * The other side kept disappearing.
		 *
		**/

		/**
		 * The other side kept disappearing.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CallProblemInterruptions(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CallProblemInterruptions.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CallProblemInterruptions.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return CallProblemInterruptions.CONSTRUCTOR;
		}
	}

	/**
	 * The speech was distorted.
	**/
	public static final class CallProblemDistortedSpeech extends CallProblem {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 379960581;

		/**
		 * The speech was distorted.
		**/
		public CallProblemDistortedSpeech() {}

		/**
		 * The speech was distorted.
		 *
		**/

		/**
		 * The speech was distorted.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CallProblemDistortedSpeech(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CallProblemDistortedSpeech.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CallProblemDistortedSpeech.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return CallProblemDistortedSpeech.CONSTRUCTOR;
		}
	}

	/**
	 * The user couldn&#039;t hear the other side.
	**/
	public static final class CallProblemSilentLocal extends CallProblem {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 253652790;

		/**
		 * The user couldn&#039;t hear the other side.
		**/
		public CallProblemSilentLocal() {}

		/**
		 * The user couldn&#039;t hear the other side.
		 *
		**/

		/**
		 * The user couldn&#039;t hear the other side.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CallProblemSilentLocal(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CallProblemSilentLocal.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CallProblemSilentLocal.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return CallProblemSilentLocal.CONSTRUCTOR;
		}
	}

	/**
	 * The other side couldn&#039;t hear the user.
	**/
	public static final class CallProblemSilentRemote extends CallProblem {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 573634714;

		/**
		 * The other side couldn&#039;t hear the user.
		**/
		public CallProblemSilentRemote() {}

		/**
		 * The other side couldn&#039;t hear the user.
		 *
		**/

		/**
		 * The other side couldn&#039;t hear the user.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CallProblemSilentRemote(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CallProblemSilentRemote.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CallProblemSilentRemote.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return CallProblemSilentRemote.CONSTRUCTOR;
		}
	}

	/**
	 * The call ended unexpectedly.
	**/
	public static final class CallProblemDropped extends CallProblem {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1207311487;

		/**
		 * The call ended unexpectedly.
		**/
		public CallProblemDropped() {}

		/**
		 * The call ended unexpectedly.
		 *
		**/

		/**
		 * The call ended unexpectedly.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CallProblemDropped(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CallProblemDropped.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CallProblemDropped.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return CallProblemDropped.CONSTRUCTOR;
		}
	}

	/**
	 * The video was distorted.
	**/
	public static final class CallProblemDistortedVideo extends CallProblem {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 385245706;

		/**
		 * The video was distorted.
		**/
		public CallProblemDistortedVideo() {}

		/**
		 * The video was distorted.
		 *
		**/

		/**
		 * The video was distorted.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CallProblemDistortedVideo(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CallProblemDistortedVideo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CallProblemDistortedVideo.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return CallProblemDistortedVideo.CONSTRUCTOR;
		}
	}

	/**
	 * The video was pixelated.
	**/
	public static final class CallProblemPixelatedVideo extends CallProblem {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2115315411;

		/**
		 * The video was pixelated.
		**/
		public CallProblemPixelatedVideo() {}

		/**
		 * The video was pixelated.
		 *
		**/

		/**
		 * The video was pixelated.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CallProblemPixelatedVideo(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CallProblemPixelatedVideo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CallProblemPixelatedVideo.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return CallProblemPixelatedVideo.CONSTRUCTOR;
		}
	}

	/**
	 * Specifies the supported call protocols.
	**/
	public static final class CallProtocol extends Object {


		/**
		 * True, if UDP peer-to-peer connections are supported.
		**/
		public boolean udpP2p;

		/**
		 * True, if connection through UDP reflectors is supported.
		**/
		public boolean udpReflector;

		/**
		 * The minimum supported API layer; use 65.
		**/
		public int minLayer;

		/**
		 * The maximum supported API layer; use 65.
		**/
		public int maxLayer;

		/**
		 * List of supported tgcalls versions.
		**/
		public String[] libraryVersions;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1075562897;

		/**
		 * Specifies the supported call protocols.
		**/
		public CallProtocol() {}

		/**
		 * Specifies the supported call protocols.
		 *
		 * @param udpP2p True, if UDP peer-to-peer connections are supported.
		 * @param udpReflector True, if connection through UDP reflectors is supported.
		 * @param minLayer The minimum supported API layer; use 65.
		 * @param maxLayer The maximum supported API layer; use 65.
		 * @param libraryVersions List of supported tgcalls versions.
		**/
		public CallProtocol(boolean udpP2p,
				boolean udpReflector,
				int minLayer,
				int maxLayer,
				String[] libraryVersions) {
			this.udpP2p = udpP2p;
			this.udpReflector = udpReflector;
			this.minLayer = minLayer;
			this.maxLayer = maxLayer;
			this.libraryVersions = libraryVersions;
		}

		/**
		 * Specifies the supported call protocols.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CallProtocol(DataInput input) throws IOException {
			this.udpP2p = input.readBoolean();
			this.udpReflector = input.readBoolean();
			this.minLayer = input.readInt();
			this.maxLayer = input.readInt();
			if (input.readBoolean()) {
				this.libraryVersions = new String[input.readInt()];
				for (int i = 0; i < this.libraryVersions.length; i++) {
					byte[] libraryVersionsTmp = new byte[input.readInt()];
					input.readFully(libraryVersionsTmp);
					this.libraryVersions[i] = new String(libraryVersionsTmp, StandardCharsets.UTF_8);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CallProtocol.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CallProtocol.CONSTRUCTOR);
			output.writeBoolean(this.udpP2p);
			output.writeBoolean(this.udpReflector);
			output.writeInt(this.minLayer);
			output.writeInt(this.maxLayer);
			if (this.libraryVersions == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.libraryVersions.length);
				for (int i = 0; i < this.libraryVersions.length; i++) {
					byte[] libraryVersionsTmp = this.libraryVersions[i].getBytes(StandardCharsets.UTF_8);
					output.writeInt(libraryVersionsTmp.length);
					output.write(libraryVersionsTmp);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CallProtocol callProtocol = (CallProtocol) o;
			if (this.udpP2p != callProtocol.udpP2p) {
				return false;
			}
			if (this.udpReflector != callProtocol.udpReflector) {
				return false;
			}
			if (this.minLayer != callProtocol.minLayer) {
				return false;
			}
			if (this.maxLayer != callProtocol.maxLayer) {
				return false;
			}
			if (!Arrays.equals(this.libraryVersions, callProtocol.libraryVersions)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.udpP2p);
			result = result * 31 + (Arrays.hashCode(this.libraryVersions));
			return result;
		}
	}

	/**
	 * Describes a server for relaying call data.
	**/
	public static final class CallServer extends Object {


		/**
		 * Server identifier.
		**/
		public long id;

		/**
		 * Server IPv4 address.
		**/
		public String ipAddress;

		/**
		 * Server IPv6 address.
		**/
		public String ipv6Address;

		/**
		 * Server port number.
		**/
		public int port;

		/**
		 * Server type.
		**/
		public CallServerType type;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1865932695;

		/**
		 * Describes a server for relaying call data.
		**/
		public CallServer() {}

		/**
		 * Describes a server for relaying call data.
		 *
		 * @param id Server identifier.
		 * @param ipAddress Server IPv4 address.
		 * @param ipv6Address Server IPv6 address.
		 * @param port Server port number.
		 * @param type Server type.
		**/
		public CallServer(long id,
				String ipAddress,
				String ipv6Address,
				int port,
				CallServerType type) {
			this.id = id;
			this.ipAddress = ipAddress;
			this.ipv6Address = ipv6Address;
			this.port = port;
			this.type = type;
		}

		/**
		 * Describes a server for relaying call data.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CallServer(DataInput input) throws IOException {
			this.id = input.readLong();
			if (input.readBoolean()) {
				byte[] ipAddressTmp = new byte[input.readInt()];
				input.readFully(ipAddressTmp);
				this.ipAddress = new String(ipAddressTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] ipv6AddressTmp = new byte[input.readInt()];
				input.readFully(ipv6AddressTmp);
				this.ipv6Address = new String(ipv6AddressTmp, StandardCharsets.UTF_8);
			}
			this.port = input.readInt();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case CallServerTypeTelegramReflector.CONSTRUCTOR: this.type = new CallServerTypeTelegramReflector(input); break;
					case CallServerTypeWebrtc.CONSTRUCTOR: this.type = new CallServerTypeWebrtc(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CallServer.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CallServer.CONSTRUCTOR);
			output.writeLong(this.id);
			if (this.ipAddress == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] ipAddressTmp = this.ipAddress.getBytes(StandardCharsets.UTF_8);
				output.writeInt(ipAddressTmp.length);
				output.write(ipAddressTmp);
			}
			if (this.ipv6Address == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] ipv6AddressTmp = this.ipv6Address.getBytes(StandardCharsets.UTF_8);
				output.writeInt(ipv6AddressTmp.length);
				output.write(ipv6AddressTmp);
			}
			output.writeInt(this.port);
			if (this.type == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.type.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CallServer callServer = (CallServer) o;
			if (this.id != callServer.id) {
				return false;
			}
			if (this.ipAddress != callServer.ipAddress) {
				return false;
			}
			if (this.ipv6Address != callServer.ipv6Address) {
				return false;
			}
			if (this.port != callServer.port) {
				return false;
			}
			if (!Objects.equals(this.type, callServer.type)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.id);
			result = result * 31 + (this.ipAddress == null ? 0 : this.ipAddress.hashCode());
			result = result * 31 + (this.ipv6Address == null ? 0 : this.ipv6Address.hashCode());
			result = result * 31 + (this.type == null ? 0 : this.type.hashCode());
			return result;
		}
	}

	/**
	 * A Telegram call reflector.
	**/
	public static final class CallServerTypeTelegramReflector extends CallServerType {


		/**
		 * A peer tag to be used with the reflector.
		**/
		public byte[] peerTag;

		/**
		 * True, if the server uses TCP instead of UDP.
		**/
		public boolean isTcp;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 850343189;

		/**
		 * A Telegram call reflector.
		**/
		public CallServerTypeTelegramReflector() {}

		/**
		 * A Telegram call reflector.
		 *
		 * @param peerTag A peer tag to be used with the reflector.
		 * @param isTcp True, if the server uses TCP instead of UDP.
		**/
		public CallServerTypeTelegramReflector(byte[] peerTag, boolean isTcp) {
			this.peerTag = peerTag;
			this.isTcp = isTcp;
		}

		/**
		 * A Telegram call reflector.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CallServerTypeTelegramReflector(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.peerTag = new byte[input.readInt()];
				input.readFully(this.peerTag);
			}
			this.isTcp = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CallServerTypeTelegramReflector.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CallServerTypeTelegramReflector.CONSTRUCTOR);
			if (this.peerTag == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.peerTag.length);
				output.write(this.peerTag);
			}
			output.writeBoolean(this.isTcp);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CallServerTypeTelegramReflector callServerTypeTelegramReflector = (CallServerTypeTelegramReflector) o;
			if (this.peerTag != callServerTypeTelegramReflector.peerTag) {
				return false;
			}
			if (this.isTcp != callServerTypeTelegramReflector.isTcp) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isTcp);
			result = result * 31 + (Arrays.hashCode(this.peerTag));
			return result;
		}
	}

	/**
	 * A WebRTC server.
	**/
	public static final class CallServerTypeWebrtc extends CallServerType {


		/**
		 * Username to be used for authentication.
		**/
		public String username;

		/**
		 * Authentication password.
		**/
		public String password;

		/**
		 * True, if the server supports TURN.
		**/
		public boolean supportsTurn;

		/**
		 * True, if the server supports STUN.
		**/
		public boolean supportsStun;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1250622821;

		/**
		 * A WebRTC server.
		**/
		public CallServerTypeWebrtc() {}

		/**
		 * A WebRTC server.
		 *
		 * @param username Username to be used for authentication.
		 * @param password Authentication password.
		 * @param supportsTurn True, if the server supports TURN.
		 * @param supportsStun True, if the server supports STUN.
		**/
		public CallServerTypeWebrtc(String username,
				String password,
				boolean supportsTurn,
				boolean supportsStun) {
			this.username = username;
			this.password = password;
			this.supportsTurn = supportsTurn;
			this.supportsStun = supportsStun;
		}

		/**
		 * A WebRTC server.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CallServerTypeWebrtc(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] usernameTmp = new byte[input.readInt()];
				input.readFully(usernameTmp);
				this.username = new String(usernameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] passwordTmp = new byte[input.readInt()];
				input.readFully(passwordTmp);
				this.password = new String(passwordTmp, StandardCharsets.UTF_8);
			}
			this.supportsTurn = input.readBoolean();
			this.supportsStun = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CallServerTypeWebrtc.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CallServerTypeWebrtc.CONSTRUCTOR);
			if (this.username == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] usernameTmp = this.username.getBytes(StandardCharsets.UTF_8);
				output.writeInt(usernameTmp.length);
				output.write(usernameTmp);
			}
			if (this.password == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] passwordTmp = this.password.getBytes(StandardCharsets.UTF_8);
				output.writeInt(passwordTmp.length);
				output.write(passwordTmp);
			}
			output.writeBoolean(this.supportsTurn);
			output.writeBoolean(this.supportsStun);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CallServerTypeWebrtc callServerTypeWebrtc = (CallServerTypeWebrtc) o;
			if (this.username != callServerTypeWebrtc.username) {
				return false;
			}
			if (this.password != callServerTypeWebrtc.password) {
				return false;
			}
			if (this.supportsTurn != callServerTypeWebrtc.supportsTurn) {
				return false;
			}
			if (this.supportsStun != callServerTypeWebrtc.supportsStun) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.supportsTurn);
			result = result * 31 + (this.username == null ? 0 : this.username.hashCode());
			result = result * 31 + (this.password == null ? 0 : this.password.hashCode());
			return result;
		}
	}

	/**
	 * The call is pending, waiting to be accepted by a user.
	**/
	public static final class CallStatePending extends CallState {


		/**
		 * True, if the call has already been created by the server.
		**/
		public boolean isCreated;

		/**
		 * True, if the call has already been received by the other party.
		**/
		public boolean isReceived;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1073048620;

		/**
		 * The call is pending, waiting to be accepted by a user.
		**/
		public CallStatePending() {}

		/**
		 * The call is pending, waiting to be accepted by a user.
		 *
		 * @param isCreated True, if the call has already been created by the server.
		 * @param isReceived True, if the call has already been received by the other party.
		**/
		public CallStatePending(boolean isCreated, boolean isReceived) {
			this.isCreated = isCreated;
			this.isReceived = isReceived;
		}

		/**
		 * The call is pending, waiting to be accepted by a user.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CallStatePending(DataInput input) throws IOException {
			this.isCreated = input.readBoolean();
			this.isReceived = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CallStatePending.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CallStatePending.CONSTRUCTOR);
			output.writeBoolean(this.isCreated);
			output.writeBoolean(this.isReceived);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CallStatePending callStatePending = (CallStatePending) o;
			if (this.isCreated != callStatePending.isCreated) {
				return false;
			}
			if (this.isReceived != callStatePending.isReceived) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isCreated);
			return result;
		}
	}

	/**
	 * The call has been answered and encryption keys are being exchanged.
	**/
	public static final class CallStateExchangingKeys extends CallState {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1848149403;

		/**
		 * The call has been answered and encryption keys are being exchanged.
		**/
		public CallStateExchangingKeys() {}

		/**
		 * The call has been answered and encryption keys are being exchanged.
		 *
		**/

		/**
		 * The call has been answered and encryption keys are being exchanged.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CallStateExchangingKeys(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CallStateExchangingKeys.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CallStateExchangingKeys.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return CallStateExchangingKeys.CONSTRUCTOR;
		}
	}

	/**
	 * The call is ready to use.
	**/
	public static final class CallStateReady extends CallState {


		/**
		 * Call protocols supported by the peer.
		**/
		public CallProtocol protocol;

		/**
		 * List of available call servers.
		**/
		public CallServer[] servers;

		/**
		 * A JSON-encoded call config.
		**/
		public String config;

		/**
		 * Call encryption key.
		**/
		public byte[] encryptionKey;

		/**
		 * Encryption key emojis fingerprint.
		**/
		public String[] emojis;

		/**
		 * True, if peer-to-peer connection is allowed by users privacy settings.
		**/
		public boolean allowP2p;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2000107571;

		/**
		 * The call is ready to use.
		**/
		public CallStateReady() {}

		/**
		 * The call is ready to use.
		 *
		 * @param protocol Call protocols supported by the peer.
		 * @param servers List of available call servers.
		 * @param config A JSON-encoded call config.
		 * @param encryptionKey Call encryption key.
		 * @param emojis Encryption key emojis fingerprint.
		 * @param allowP2p True, if peer-to-peer connection is allowed by users privacy settings.
		**/
		public CallStateReady(CallProtocol protocol,
				CallServer[] servers,
				String config,
				byte[] encryptionKey,
				String[] emojis,
				boolean allowP2p) {
			this.protocol = protocol;
			this.servers = servers;
			this.config = config;
			this.encryptionKey = encryptionKey;
			this.emojis = emojis;
			this.allowP2p = allowP2p;
		}

		/**
		 * The call is ready to use.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CallStateReady(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (CallProtocol.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.protocol = new CallProtocol(input);
			}
			if (input.readBoolean()) {
				this.servers = new CallServer[input.readInt()];
				for (int i = 0; i < this.servers.length; i++) {
					if (CallServer.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.servers[i] = new CallServer(input);
				}
			}
			if (input.readBoolean()) {
				byte[] configTmp = new byte[input.readInt()];
				input.readFully(configTmp);
				this.config = new String(configTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				this.encryptionKey = new byte[input.readInt()];
				input.readFully(this.encryptionKey);
			}
			if (input.readBoolean()) {
				this.emojis = new String[input.readInt()];
				for (int i = 0; i < this.emojis.length; i++) {
					byte[] emojisTmp = new byte[input.readInt()];
					input.readFully(emojisTmp);
					this.emojis[i] = new String(emojisTmp, StandardCharsets.UTF_8);
				}
			}
			this.allowP2p = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CallStateReady.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CallStateReady.CONSTRUCTOR);
			if (this.protocol == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.protocol.serialize(output);
			}
			if (this.servers == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.servers.length);
				for (int i = 0; i < this.servers.length; i++) {
					this.servers[i].serialize(output);
				}
			}
			if (this.config == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] configTmp = this.config.getBytes(StandardCharsets.UTF_8);
				output.writeInt(configTmp.length);
				output.write(configTmp);
			}
			if (this.encryptionKey == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.encryptionKey.length);
				output.write(this.encryptionKey);
			}
			if (this.emojis == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.emojis.length);
				for (int i = 0; i < this.emojis.length; i++) {
					byte[] emojisTmp = this.emojis[i].getBytes(StandardCharsets.UTF_8);
					output.writeInt(emojisTmp.length);
					output.write(emojisTmp);
				}
			}
			output.writeBoolean(this.allowP2p);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CallStateReady callStateReady = (CallStateReady) o;
			if (!Objects.equals(this.protocol, callStateReady.protocol)) {
				return false;
			}
			if (!Arrays.equals(this.servers, callStateReady.servers)) {
				return false;
			}
			if (this.config != callStateReady.config) {
				return false;
			}
			if (this.encryptionKey != callStateReady.encryptionKey) {
				return false;
			}
			if (!Arrays.equals(this.emojis, callStateReady.emojis)) {
				return false;
			}
			if (this.allowP2p != callStateReady.allowP2p) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.allowP2p);
			result = result * 31 + (this.protocol == null ? 0 : this.protocol.hashCode());
			result = result * 31 + (Arrays.hashCode(this.servers));
			result = result * 31 + (this.config == null ? 0 : this.config.hashCode());
			result = result * 31 + (Arrays.hashCode(this.encryptionKey));
			result = result * 31 + (Arrays.hashCode(this.emojis));
			return result;
		}
	}

	/**
	 * The call is hanging up after discardCall has been called.
	**/
	public static final class CallStateHangingUp extends CallState {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2133790038;

		/**
		 * The call is hanging up after discardCall has been called.
		**/
		public CallStateHangingUp() {}

		/**
		 * The call is hanging up after discardCall has been called.
		 *
		**/

		/**
		 * The call is hanging up after discardCall has been called.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CallStateHangingUp(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CallStateHangingUp.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CallStateHangingUp.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return CallStateHangingUp.CONSTRUCTOR;
		}
	}

	/**
	 * The call has ended successfully.
	**/
	public static final class CallStateDiscarded extends CallState {


		/**
		 * The reason, why the call has ended.
		**/
		public CallDiscardReason reason;

		/**
		 * True, if the call rating must be sent to the server.
		**/
		public boolean needRating;

		/**
		 * True, if the call debug information must be sent to the server.
		**/
		public boolean needDebugInformation;

		/**
		 * True, if the call log must be sent to the server.
		**/
		public boolean needLog;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1394310213;

		/**
		 * The call has ended successfully.
		**/
		public CallStateDiscarded() {}

		/**
		 * The call has ended successfully.
		 *
		 * @param reason The reason, why the call has ended.
		 * @param needRating True, if the call rating must be sent to the server.
		 * @param needDebugInformation True, if the call debug information must be sent to the server.
		 * @param needLog True, if the call log must be sent to the server.
		**/
		public CallStateDiscarded(CallDiscardReason reason,
				boolean needRating,
				boolean needDebugInformation,
				boolean needLog) {
			this.reason = reason;
			this.needRating = needRating;
			this.needDebugInformation = needDebugInformation;
			this.needLog = needLog;
		}

		/**
		 * The call has ended successfully.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CallStateDiscarded(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case CallDiscardReasonEmpty.CONSTRUCTOR: this.reason = new CallDiscardReasonEmpty(input); break;
					case CallDiscardReasonMissed.CONSTRUCTOR: this.reason = new CallDiscardReasonMissed(input); break;
					case CallDiscardReasonDeclined.CONSTRUCTOR: this.reason = new CallDiscardReasonDeclined(input); break;
					case CallDiscardReasonDisconnected.CONSTRUCTOR: this.reason = new CallDiscardReasonDisconnected(input); break;
					case CallDiscardReasonHungUp.CONSTRUCTOR: this.reason = new CallDiscardReasonHungUp(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.needRating = input.readBoolean();
			this.needDebugInformation = input.readBoolean();
			this.needLog = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CallStateDiscarded.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CallStateDiscarded.CONSTRUCTOR);
			if (this.reason == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.reason.serialize(output);
			}
			output.writeBoolean(this.needRating);
			output.writeBoolean(this.needDebugInformation);
			output.writeBoolean(this.needLog);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CallStateDiscarded callStateDiscarded = (CallStateDiscarded) o;
			if (!Objects.equals(this.reason, callStateDiscarded.reason)) {
				return false;
			}
			if (this.needRating != callStateDiscarded.needRating) {
				return false;
			}
			if (this.needDebugInformation != callStateDiscarded.needDebugInformation) {
				return false;
			}
			if (this.needLog != callStateDiscarded.needLog) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.needRating);
			result = result * 31 + (this.reason == null ? 0 : this.reason.hashCode());
			return result;
		}
	}

	/**
	 * The call has ended with an error.
	**/
	public static final class CallStateError extends CallState {


		/**
		 * Error. An error with the code 4005000 will be returned if an outgoing call is missed because of an expired timeout.
		**/
		public Error error;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -975215467;

		/**
		 * The call has ended with an error.
		**/
		public CallStateError() {}

		/**
		 * The call has ended with an error.
		 *
		 * @param error Error. An error with the code 4005000 will be returned if an outgoing call is missed because of an expired timeout.
		**/
		public CallStateError(Error error) {
			this.error = error;
		}

		/**
		 * The call has ended with an error.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CallStateError(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Error.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.error = new Error(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CallStateError.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CallStateError.CONSTRUCTOR);
			if (this.error == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.error.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CallStateError callStateError = (CallStateError) o;
			if (!Objects.equals(this.error, callStateError.error)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.error == null ? 0 : this.error.hashCode();
		}
	}

	/**
	 * Contains a bot&#039;s answer to a callback query.
	**/
	public static final class CallbackQueryAnswer extends Object {


		/**
		 * Text of the answer.
		**/
		public String text;

		/**
		 * True, if an alert must be shown to the user instead of a toast notification.
		**/
		public boolean showAlert;

		/**
		 * URL to be opened.
		**/
		public String url;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 360867933;

		/**
		 * Contains a bot&#039;s answer to a callback query.
		**/
		public CallbackQueryAnswer() {}

		/**
		 * Contains a bot&#039;s answer to a callback query.
		 *
		 * @param text Text of the answer.
		 * @param showAlert True, if an alert must be shown to the user instead of a toast notification.
		 * @param url URL to be opened.
		**/
		public CallbackQueryAnswer(String text, boolean showAlert, String url) {
			this.text = text;
			this.showAlert = showAlert;
			this.url = url;
		}

		/**
		 * Contains a bot&#039;s answer to a callback query.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CallbackQueryAnswer(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] textTmp = new byte[input.readInt()];
				input.readFully(textTmp);
				this.text = new String(textTmp, StandardCharsets.UTF_8);
			}
			this.showAlert = input.readBoolean();
			if (input.readBoolean()) {
				byte[] urlTmp = new byte[input.readInt()];
				input.readFully(urlTmp);
				this.url = new String(urlTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CallbackQueryAnswer.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CallbackQueryAnswer.CONSTRUCTOR);
			if (this.text == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] textTmp = this.text.getBytes(StandardCharsets.UTF_8);
				output.writeInt(textTmp.length);
				output.write(textTmp);
			}
			output.writeBoolean(this.showAlert);
			if (this.url == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] urlTmp = this.url.getBytes(StandardCharsets.UTF_8);
				output.writeInt(urlTmp.length);
				output.write(urlTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CallbackQueryAnswer callbackQueryAnswer = (CallbackQueryAnswer) o;
			if (this.text != callbackQueryAnswer.text) {
				return false;
			}
			if (this.showAlert != callbackQueryAnswer.showAlert) {
				return false;
			}
			if (this.url != callbackQueryAnswer.url) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.showAlert);
			result = result * 31 + (this.text == null ? 0 : this.text.hashCode());
			result = result * 31 + (this.url == null ? 0 : this.url.hashCode());
			return result;
		}
	}

	/**
	 * The payload for a general callback button.
	**/
	public static final class CallbackQueryPayloadData extends CallbackQueryPayload {


		/**
		 * Data that was attached to the callback button.
		**/
		public byte[] data;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1977729946;

		/**
		 * The payload for a general callback button.
		**/
		public CallbackQueryPayloadData() {}

		/**
		 * The payload for a general callback button.
		 *
		 * @param data Data that was attached to the callback button.
		**/
		public CallbackQueryPayloadData(byte[] data) {
			this.data = data;
		}

		/**
		 * The payload for a general callback button.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CallbackQueryPayloadData(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.data = new byte[input.readInt()];
				input.readFully(this.data);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CallbackQueryPayloadData.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CallbackQueryPayloadData.CONSTRUCTOR);
			if (this.data == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.data.length);
				output.write(this.data);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CallbackQueryPayloadData callbackQueryPayloadData = (CallbackQueryPayloadData) o;
			if (this.data != callbackQueryPayloadData.data) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.data);
		}
	}

	/**
	 * The payload for a callback button requiring password.
	**/
	public static final class CallbackQueryPayloadDataWithPassword extends CallbackQueryPayload {


		/**
		 * The 2-step verification password for the current user.
		**/
		public String password;

		/**
		 * Data that was attached to the callback button.
		**/
		public byte[] data;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1340266738;

		/**
		 * The payload for a callback button requiring password.
		**/
		public CallbackQueryPayloadDataWithPassword() {}

		/**
		 * The payload for a callback button requiring password.
		 *
		 * @param password The 2-step verification password for the current user.
		 * @param data Data that was attached to the callback button.
		**/
		public CallbackQueryPayloadDataWithPassword(String password, byte[] data) {
			this.password = password;
			this.data = data;
		}

		/**
		 * The payload for a callback button requiring password.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CallbackQueryPayloadDataWithPassword(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] passwordTmp = new byte[input.readInt()];
				input.readFully(passwordTmp);
				this.password = new String(passwordTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				this.data = new byte[input.readInt()];
				input.readFully(this.data);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CallbackQueryPayloadDataWithPassword.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CallbackQueryPayloadDataWithPassword.CONSTRUCTOR);
			if (this.password == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] passwordTmp = this.password.getBytes(StandardCharsets.UTF_8);
				output.writeInt(passwordTmp.length);
				output.write(passwordTmp);
			}
			if (this.data == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.data.length);
				output.write(this.data);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CallbackQueryPayloadDataWithPassword callbackQueryPayloadDataWithPassword = (CallbackQueryPayloadDataWithPassword) o;
			if (this.password != callbackQueryPayloadDataWithPassword.password) {
				return false;
			}
			if (this.data != callbackQueryPayloadDataWithPassword.data) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.password == null ? 0 : this.password.hashCode();
			result = result * 31 + (Arrays.hashCode(this.data));
			return result;
		}
	}

	/**
	 * The payload for a game callback button.
	**/
	public static final class CallbackQueryPayloadGame extends CallbackQueryPayload {


		/**
		 * A short name of the game that was attached to the callback button.
		**/
		public String gameShortName;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1303571512;

		/**
		 * The payload for a game callback button.
		**/
		public CallbackQueryPayloadGame() {}

		/**
		 * The payload for a game callback button.
		 *
		 * @param gameShortName A short name of the game that was attached to the callback button.
		**/
		public CallbackQueryPayloadGame(String gameShortName) {
			this.gameShortName = gameShortName;
		}

		/**
		 * The payload for a game callback button.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CallbackQueryPayloadGame(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] gameShortNameTmp = new byte[input.readInt()];
				input.readFully(gameShortNameTmp);
				this.gameShortName = new String(gameShortNameTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CallbackQueryPayloadGame.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CallbackQueryPayloadGame.CONSTRUCTOR);
			if (this.gameShortName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] gameShortNameTmp = this.gameShortName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(gameShortNameTmp.length);
				output.write(gameShortNameTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CallbackQueryPayloadGame callbackQueryPayloadGame = (CallbackQueryPayloadGame) o;
			if (this.gameShortName != callbackQueryPayloadGame.gameShortName) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.gameShortName == null ? 0 : this.gameShortName.hashCode();
		}
	}

	/**
	 * The session can be used.
	**/
	public static final class CanTransferOwnershipResultOk extends CanTransferOwnershipResult {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -89881021;

		/**
		 * The session can be used.
		**/
		public CanTransferOwnershipResultOk() {}

		/**
		 * The session can be used.
		 *
		**/

		/**
		 * The session can be used.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CanTransferOwnershipResultOk(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CanTransferOwnershipResultOk.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CanTransferOwnershipResultOk.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return CanTransferOwnershipResultOk.CONSTRUCTOR;
		}
	}

	/**
	 * The 2-step verification needs to be enabled first.
	**/
	public static final class CanTransferOwnershipResultPasswordNeeded extends CanTransferOwnershipResult {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1548372703;

		/**
		 * The 2-step verification needs to be enabled first.
		**/
		public CanTransferOwnershipResultPasswordNeeded() {}

		/**
		 * The 2-step verification needs to be enabled first.
		 *
		**/

		/**
		 * The 2-step verification needs to be enabled first.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CanTransferOwnershipResultPasswordNeeded(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CanTransferOwnershipResultPasswordNeeded.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CanTransferOwnershipResultPasswordNeeded.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return CanTransferOwnershipResultPasswordNeeded.CONSTRUCTOR;
		}
	}

	/**
	 * The 2-step verification was enabled recently, user needs to wait.
	**/
	public static final class CanTransferOwnershipResultPasswordTooFresh extends CanTransferOwnershipResult {


		/**
		 * Time left before the session can be used to transfer ownership of a chat, in seconds.
		**/
		public int retryAfter;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 811440913;

		/**
		 * The 2-step verification was enabled recently, user needs to wait.
		**/
		public CanTransferOwnershipResultPasswordTooFresh() {}

		/**
		 * The 2-step verification was enabled recently, user needs to wait.
		 *
		 * @param retryAfter Time left before the session can be used to transfer ownership of a chat, in seconds.
		**/
		public CanTransferOwnershipResultPasswordTooFresh(int retryAfter) {
			this.retryAfter = retryAfter;
		}

		/**
		 * The 2-step verification was enabled recently, user needs to wait.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CanTransferOwnershipResultPasswordTooFresh(DataInput input) throws IOException {
			this.retryAfter = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CanTransferOwnershipResultPasswordTooFresh.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CanTransferOwnershipResultPasswordTooFresh.CONSTRUCTOR);
			output.writeInt(this.retryAfter);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CanTransferOwnershipResultPasswordTooFresh canTransferOwnershipResultPasswordTooFresh = (CanTransferOwnershipResultPasswordTooFresh) o;
			if (this.retryAfter != canTransferOwnershipResultPasswordTooFresh.retryAfter) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.retryAfter);
		}
	}

	/**
	 * The session was created recently, user needs to wait.
	**/
	public static final class CanTransferOwnershipResultSessionTooFresh extends CanTransferOwnershipResult {


		/**
		 * Time left before the session can be used to transfer ownership of a chat, in seconds.
		**/
		public int retryAfter;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 984664289;

		/**
		 * The session was created recently, user needs to wait.
		**/
		public CanTransferOwnershipResultSessionTooFresh() {}

		/**
		 * The session was created recently, user needs to wait.
		 *
		 * @param retryAfter Time left before the session can be used to transfer ownership of a chat, in seconds.
		**/
		public CanTransferOwnershipResultSessionTooFresh(int retryAfter) {
			this.retryAfter = retryAfter;
		}

		/**
		 * The session was created recently, user needs to wait.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CanTransferOwnershipResultSessionTooFresh(DataInput input) throws IOException {
			this.retryAfter = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CanTransferOwnershipResultSessionTooFresh.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CanTransferOwnershipResultSessionTooFresh.CONSTRUCTOR);
			output.writeInt(this.retryAfter);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CanTransferOwnershipResultSessionTooFresh canTransferOwnershipResultSessionTooFresh = (CanTransferOwnershipResultSessionTooFresh) o;
			if (this.retryAfter != canTransferOwnershipResultSessionTooFresh.retryAfter) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.retryAfter);
		}
	}

	/**
	 * A chat. (Can be a private chat, basic group, supergroup, or secret
	 * chat.)
	**/
	public static final class Chat extends Object {


		/**
		 * Chat unique identifier.
		**/
		public long id;

		/**
		 * Type of the chat.
		**/
		public ChatType type;

		/**
		 * Chat title.
		**/
		public String title;

		/**
		 * Chat photo; may be null.
		**/
		public ChatPhotoInfo photo;

		/**
		 * Actions that non-administrator chat members are allowed to take in the chat.
		**/
		public ChatPermissions permissions;

		/**
		 * Last message in the chat; may be null.
		**/
		public Message lastMessage;

		/**
		 * Positions of the chat in chat lists.
		**/
		public ChatPosition[] positions;

		/**
		 * Identifier of a user or chat that is selected to send messages in the chat; may be null if the user can&#039;t change message sender.
		**/
		public MessageSender messageSenderId;

		/**
		 * True, if chat content can&#039;t be saved locally, forwarded, or copied.
		**/
		public boolean hasProtectedContent;

		/**
		 * True, if translation of all messages in the chat must be suggested to the user.
		**/
		public boolean isTranslatable;

		/**
		 * True, if the chat is marked as unread.
		**/
		public boolean isMarkedAsUnread;

		/**
		 * True, if the chat is blocked by the current user and private messages from the chat can&#039;t be received.
		**/
		public boolean isBlocked;

		/**
		 * True, if the chat has scheduled messages.
		**/
		public boolean hasScheduledMessages;

		/**
		 * True, if the chat messages can be deleted only for the current user while other users will continue to see the messages.
		**/
		public boolean canBeDeletedOnlyForSelf;

		/**
		 * True, if the chat messages can be deleted for all users.
		**/
		public boolean canBeDeletedForAllUsers;

		/**
		 * True, if the chat can be reported to Telegram moderators through reportChat or reportChatPhoto.
		**/
		public boolean canBeReported;

		/**
		 * Default value of the disableNotification parameter, used when a message is sent to the chat.
		**/
		public boolean defaultDisableNotification;

		/**
		 * Number of unread messages in the chat.
		**/
		public int unreadCount;

		/**
		 * Identifier of the last read incoming message.
		**/
		public long lastReadInboxMessageId;

		/**
		 * Identifier of the last read outgoing message.
		**/
		public long lastReadOutboxMessageId;

		/**
		 * Number of unread messages with a mention/reply in the chat.
		**/
		public int unreadMentionCount;

		/**
		 * Number of messages with unread reactions in the chat.
		**/
		public int unreadReactionCount;

		/**
		 * Notification settings for the chat.
		**/
		public ChatNotificationSettings notificationSettings;

		/**
		 * Types of reaction, available in the chat.
		**/
		public ChatAvailableReactions availableReactions;

		/**
		 * Current message auto-delete or self-destruct timer setting for the chat, in seconds; 0 if disabled. Self-destruct timer in secret chats starts after the message or its content is viewed. Auto-delete timer in other chats starts from the send date.
		**/
		public int messageAutoDeleteTime;

		/**
		 * Background set for the chat; may be null if none.
		**/
		public ChatBackground background;

		/**
		 * If non-empty, name of a theme, set for the chat.
		**/
		public String themeName;

		/**
		 * Information about actions which must be possible to do through the chat action bar; may be null.
		**/
		public ChatActionBar actionBar;

		/**
		 * Information about video chat of the chat.
		**/
		public VideoChat videoChat;

		/**
		 * Information about pending join requests; may be null.
		**/
		public ChatJoinRequestsInfo pendingJoinRequests;

		/**
		 * Identifier of the message from which reply markup needs to be used; 0 if there is no default custom reply markup in the chat.
		**/
		public long replyMarkupMessageId;

		/**
		 * A draft of a message in the chat; may be null.
		**/
		public DraftMessage draftMessage;

		/**
		 * Application-specific data associated with the chat. (For example, the chat scroll position or local chat notification settings can be stored here.) Persistent if the message database is used.
		**/
		public String clientData;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 356800780;

		/**
		 * A chat. (Can be a private chat, basic group, supergroup, or secret chat.)
		**/
		public Chat() {}

		/**
		 * A chat. (Can be a private chat, basic group, supergroup, or secret chat.)
		 *
		 * @param id Chat unique identifier.
		 * @param type Type of the chat.
		 * @param title Chat title.
		 * @param photo Chat photo; may be null.
		 * @param permissions Actions that non-administrator chat members are allowed to take in the chat.
		 * @param lastMessage Last message in the chat; may be null.
		 * @param positions Positions of the chat in chat lists.
		 * @param messageSenderId Identifier of a user or chat that is selected to send messages in the chat; may be null if the user can&#039;t change message sender.
		 * @param hasProtectedContent True, if chat content can&#039;t be saved locally, forwarded, or copied.
		 * @param isTranslatable True, if translation of all messages in the chat must be suggested to the user.
		 * @param isMarkedAsUnread True, if the chat is marked as unread.
		 * @param isBlocked True, if the chat is blocked by the current user and private messages from the chat can&#039;t be received.
		 * @param hasScheduledMessages True, if the chat has scheduled messages.
		 * @param canBeDeletedOnlyForSelf True, if the chat messages can be deleted only for the current user while other users will continue to see the messages.
		 * @param canBeDeletedForAllUsers True, if the chat messages can be deleted for all users.
		 * @param canBeReported True, if the chat can be reported to Telegram moderators through reportChat or reportChatPhoto.
		 * @param defaultDisableNotification Default value of the disableNotification parameter, used when a message is sent to the chat.
		 * @param unreadCount Number of unread messages in the chat.
		 * @param lastReadInboxMessageId Identifier of the last read incoming message.
		 * @param lastReadOutboxMessageId Identifier of the last read outgoing message.
		 * @param unreadMentionCount Number of unread messages with a mention/reply in the chat.
		 * @param unreadReactionCount Number of messages with unread reactions in the chat.
		 * @param notificationSettings Notification settings for the chat.
		 * @param availableReactions Types of reaction, available in the chat.
		 * @param messageAutoDeleteTime Current message auto-delete or self-destruct timer setting for the chat, in seconds; 0 if disabled. Self-destruct timer in secret chats starts after the message or its content is viewed. Auto-delete timer in other chats starts from the send date.
		 * @param background Background set for the chat; may be null if none.
		 * @param themeName If non-empty, name of a theme, set for the chat.
		 * @param actionBar Information about actions which must be possible to do through the chat action bar; may be null.
		 * @param videoChat Information about video chat of the chat.
		 * @param pendingJoinRequests Information about pending join requests; may be null.
		 * @param replyMarkupMessageId Identifier of the message from which reply markup needs to be used; 0 if there is no default custom reply markup in the chat.
		 * @param draftMessage A draft of a message in the chat; may be null.
		 * @param clientData Application-specific data associated with the chat. (For example, the chat scroll position or local chat notification settings can be stored here.) Persistent if the message database is used.
		**/
		public Chat(long id,
				ChatType type,
				String title,
				ChatPhotoInfo photo,
				ChatPermissions permissions,
				Message lastMessage,
				ChatPosition[] positions,
				MessageSender messageSenderId,
				boolean hasProtectedContent,
				boolean isTranslatable,
				boolean isMarkedAsUnread,
				boolean isBlocked,
				boolean hasScheduledMessages,
				boolean canBeDeletedOnlyForSelf,
				boolean canBeDeletedForAllUsers,
				boolean canBeReported,
				boolean defaultDisableNotification,
				int unreadCount,
				long lastReadInboxMessageId,
				long lastReadOutboxMessageId,
				int unreadMentionCount,
				int unreadReactionCount,
				ChatNotificationSettings notificationSettings,
				ChatAvailableReactions availableReactions,
				int messageAutoDeleteTime,
				ChatBackground background,
				String themeName,
				ChatActionBar actionBar,
				VideoChat videoChat,
				ChatJoinRequestsInfo pendingJoinRequests,
				long replyMarkupMessageId,
				DraftMessage draftMessage,
				String clientData) {
			this.id = id;
			this.type = type;
			this.title = title;
			this.photo = photo;
			this.permissions = permissions;
			this.lastMessage = lastMessage;
			this.positions = positions;
			this.messageSenderId = messageSenderId;
			this.hasProtectedContent = hasProtectedContent;
			this.isTranslatable = isTranslatable;
			this.isMarkedAsUnread = isMarkedAsUnread;
			this.isBlocked = isBlocked;
			this.hasScheduledMessages = hasScheduledMessages;
			this.canBeDeletedOnlyForSelf = canBeDeletedOnlyForSelf;
			this.canBeDeletedForAllUsers = canBeDeletedForAllUsers;
			this.canBeReported = canBeReported;
			this.defaultDisableNotification = defaultDisableNotification;
			this.unreadCount = unreadCount;
			this.lastReadInboxMessageId = lastReadInboxMessageId;
			this.lastReadOutboxMessageId = lastReadOutboxMessageId;
			this.unreadMentionCount = unreadMentionCount;
			this.unreadReactionCount = unreadReactionCount;
			this.notificationSettings = notificationSettings;
			this.availableReactions = availableReactions;
			this.messageAutoDeleteTime = messageAutoDeleteTime;
			this.background = background;
			this.themeName = themeName;
			this.actionBar = actionBar;
			this.videoChat = videoChat;
			this.pendingJoinRequests = pendingJoinRequests;
			this.replyMarkupMessageId = replyMarkupMessageId;
			this.draftMessage = draftMessage;
			this.clientData = clientData;
		}

		/**
		 * A chat. (Can be a private chat, basic group, supergroup, or secret chat.)
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public Chat(DataInput input) throws IOException {
			this.id = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ChatTypePrivate.CONSTRUCTOR: this.type = new ChatTypePrivate(input); break;
					case ChatTypeBasicGroup.CONSTRUCTOR: this.type = new ChatTypeBasicGroup(input); break;
					case ChatTypeSupergroup.CONSTRUCTOR: this.type = new ChatTypeSupergroup(input); break;
					case ChatTypeSecret.CONSTRUCTOR: this.type = new ChatTypeSecret(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (ChatPhotoInfo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.photo = new ChatPhotoInfo(input);
			}
			if (input.readBoolean()) {
				if (ChatPermissions.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.permissions = new ChatPermissions(input);
			}
			if (input.readBoolean()) {
				if (Message.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.lastMessage = new Message(input);
			}
			if (input.readBoolean()) {
				this.positions = new ChatPosition[input.readInt()];
				for (int i = 0; i < this.positions.length; i++) {
					if (ChatPosition.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.positions[i] = new ChatPosition(input);
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case MessageSenderUser.CONSTRUCTOR: this.messageSenderId = new MessageSenderUser(input); break;
					case MessageSenderChat.CONSTRUCTOR: this.messageSenderId = new MessageSenderChat(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.hasProtectedContent = input.readBoolean();
			this.isTranslatable = input.readBoolean();
			this.isMarkedAsUnread = input.readBoolean();
			this.isBlocked = input.readBoolean();
			this.hasScheduledMessages = input.readBoolean();
			this.canBeDeletedOnlyForSelf = input.readBoolean();
			this.canBeDeletedForAllUsers = input.readBoolean();
			this.canBeReported = input.readBoolean();
			this.defaultDisableNotification = input.readBoolean();
			this.unreadCount = input.readInt();
			this.lastReadInboxMessageId = input.readLong();
			this.lastReadOutboxMessageId = input.readLong();
			this.unreadMentionCount = input.readInt();
			this.unreadReactionCount = input.readInt();
			if (input.readBoolean()) {
				if (ChatNotificationSettings.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.notificationSettings = new ChatNotificationSettings(input);
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ChatAvailableReactionsAll.CONSTRUCTOR: this.availableReactions = new ChatAvailableReactionsAll(input); break;
					case ChatAvailableReactionsSome.CONSTRUCTOR: this.availableReactions = new ChatAvailableReactionsSome(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.messageAutoDeleteTime = input.readInt();
			if (input.readBoolean()) {
				if (ChatBackground.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.background = new ChatBackground(input);
			}
			if (input.readBoolean()) {
				byte[] themeNameTmp = new byte[input.readInt()];
				input.readFully(themeNameTmp);
				this.themeName = new String(themeNameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ChatActionBarReportSpam.CONSTRUCTOR: this.actionBar = new ChatActionBarReportSpam(input); break;
					case ChatActionBarReportUnrelatedLocation.CONSTRUCTOR: this.actionBar = new ChatActionBarReportUnrelatedLocation(input); break;
					case ChatActionBarInviteMembers.CONSTRUCTOR: this.actionBar = new ChatActionBarInviteMembers(input); break;
					case ChatActionBarReportAddBlock.CONSTRUCTOR: this.actionBar = new ChatActionBarReportAddBlock(input); break;
					case ChatActionBarAddContact.CONSTRUCTOR: this.actionBar = new ChatActionBarAddContact(input); break;
					case ChatActionBarSharePhoneNumber.CONSTRUCTOR: this.actionBar = new ChatActionBarSharePhoneNumber(input); break;
					case ChatActionBarJoinRequest.CONSTRUCTOR: this.actionBar = new ChatActionBarJoinRequest(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				if (VideoChat.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.videoChat = new VideoChat(input);
			}
			if (input.readBoolean()) {
				if (ChatJoinRequestsInfo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.pendingJoinRequests = new ChatJoinRequestsInfo(input);
			}
			this.replyMarkupMessageId = input.readLong();
			if (input.readBoolean()) {
				if (DraftMessage.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.draftMessage = new DraftMessage(input);
			}
			if (input.readBoolean()) {
				byte[] clientDataTmp = new byte[input.readInt()];
				input.readFully(clientDataTmp);
				this.clientData = new String(clientDataTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return Chat.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(Chat.CONSTRUCTOR);
			output.writeLong(this.id);
			if (this.type == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.type.serialize(output);
			}
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
			if (this.photo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.photo.serialize(output);
			}
			if (this.permissions == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.permissions.serialize(output);
			}
			if (this.lastMessage == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.lastMessage.serialize(output);
			}
			if (this.positions == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.positions.length);
				for (int i = 0; i < this.positions.length; i++) {
					this.positions[i].serialize(output);
				}
			}
			if (this.messageSenderId == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.messageSenderId.serialize(output);
			}
			output.writeBoolean(this.hasProtectedContent);
			output.writeBoolean(this.isTranslatable);
			output.writeBoolean(this.isMarkedAsUnread);
			output.writeBoolean(this.isBlocked);
			output.writeBoolean(this.hasScheduledMessages);
			output.writeBoolean(this.canBeDeletedOnlyForSelf);
			output.writeBoolean(this.canBeDeletedForAllUsers);
			output.writeBoolean(this.canBeReported);
			output.writeBoolean(this.defaultDisableNotification);
			output.writeInt(this.unreadCount);
			output.writeLong(this.lastReadInboxMessageId);
			output.writeLong(this.lastReadOutboxMessageId);
			output.writeInt(this.unreadMentionCount);
			output.writeInt(this.unreadReactionCount);
			if (this.notificationSettings == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.notificationSettings.serialize(output);
			}
			if (this.availableReactions == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.availableReactions.serialize(output);
			}
			output.writeInt(this.messageAutoDeleteTime);
			if (this.background == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.background.serialize(output);
			}
			if (this.themeName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] themeNameTmp = this.themeName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(themeNameTmp.length);
				output.write(themeNameTmp);
			}
			if (this.actionBar == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.actionBar.serialize(output);
			}
			if (this.videoChat == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.videoChat.serialize(output);
			}
			if (this.pendingJoinRequests == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.pendingJoinRequests.serialize(output);
			}
			output.writeLong(this.replyMarkupMessageId);
			if (this.draftMessage == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.draftMessage.serialize(output);
			}
			if (this.clientData == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] clientDataTmp = this.clientData.getBytes(StandardCharsets.UTF_8);
				output.writeInt(clientDataTmp.length);
				output.write(clientDataTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			Chat chat = (Chat) o;
			if (this.id != chat.id) {
				return false;
			}
			if (!Objects.equals(this.type, chat.type)) {
				return false;
			}
			if (this.title != chat.title) {
				return false;
			}
			if (!Objects.equals(this.photo, chat.photo)) {
				return false;
			}
			if (!Objects.equals(this.permissions, chat.permissions)) {
				return false;
			}
			if (!Objects.equals(this.lastMessage, chat.lastMessage)) {
				return false;
			}
			if (!Arrays.equals(this.positions, chat.positions)) {
				return false;
			}
			if (!Objects.equals(this.messageSenderId, chat.messageSenderId)) {
				return false;
			}
			if (this.hasProtectedContent != chat.hasProtectedContent) {
				return false;
			}
			if (this.isTranslatable != chat.isTranslatable) {
				return false;
			}
			if (this.isMarkedAsUnread != chat.isMarkedAsUnread) {
				return false;
			}
			if (this.isBlocked != chat.isBlocked) {
				return false;
			}
			if (this.hasScheduledMessages != chat.hasScheduledMessages) {
				return false;
			}
			if (this.canBeDeletedOnlyForSelf != chat.canBeDeletedOnlyForSelf) {
				return false;
			}
			if (this.canBeDeletedForAllUsers != chat.canBeDeletedForAllUsers) {
				return false;
			}
			if (this.canBeReported != chat.canBeReported) {
				return false;
			}
			if (this.defaultDisableNotification != chat.defaultDisableNotification) {
				return false;
			}
			if (this.unreadCount != chat.unreadCount) {
				return false;
			}
			if (this.lastReadInboxMessageId != chat.lastReadInboxMessageId) {
				return false;
			}
			if (this.lastReadOutboxMessageId != chat.lastReadOutboxMessageId) {
				return false;
			}
			if (this.unreadMentionCount != chat.unreadMentionCount) {
				return false;
			}
			if (this.unreadReactionCount != chat.unreadReactionCount) {
				return false;
			}
			if (!Objects.equals(this.notificationSettings, chat.notificationSettings)) {
				return false;
			}
			if (!Objects.equals(this.availableReactions, chat.availableReactions)) {
				return false;
			}
			if (this.messageAutoDeleteTime != chat.messageAutoDeleteTime) {
				return false;
			}
			if (!Objects.equals(this.background, chat.background)) {
				return false;
			}
			if (this.themeName != chat.themeName) {
				return false;
			}
			if (!Objects.equals(this.actionBar, chat.actionBar)) {
				return false;
			}
			if (!Objects.equals(this.videoChat, chat.videoChat)) {
				return false;
			}
			if (!Objects.equals(this.pendingJoinRequests, chat.pendingJoinRequests)) {
				return false;
			}
			if (this.replyMarkupMessageId != chat.replyMarkupMessageId) {
				return false;
			}
			if (!Objects.equals(this.draftMessage, chat.draftMessage)) {
				return false;
			}
			if (this.clientData != chat.clientData) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.id);
			result = result * 31 + (this.type == null ? 0 : this.type.hashCode());
			result = result * 31 + (this.title == null ? 0 : this.title.hashCode());
			result = result * 31 + (this.photo == null ? 0 : this.photo.hashCode());
			result = result * 31 + (this.permissions == null ? 0 : this.permissions.hashCode());
			result = result * 31 + (this.lastMessage == null ? 0 : this.lastMessage.hashCode());
			result = result * 31 + (Arrays.hashCode(this.positions));
			result = result * 31 + (this.messageSenderId == null ? 0 : this.messageSenderId.hashCode());
			result = result * 31 + (this.notificationSettings == null ? 0 : this.notificationSettings.hashCode());
			result = result * 31 + (this.availableReactions == null ? 0 : this.availableReactions.hashCode());
			result = result * 31 + (this.background == null ? 0 : this.background.hashCode());
			result = result * 31 + (this.themeName == null ? 0 : this.themeName.hashCode());
			result = result * 31 + (this.actionBar == null ? 0 : this.actionBar.hashCode());
			result = result * 31 + (this.videoChat == null ? 0 : this.videoChat.hashCode());
			result = result * 31 + (this.pendingJoinRequests == null ? 0 : this.pendingJoinRequests.hashCode());
			result = result * 31 + (this.draftMessage == null ? 0 : this.draftMessage.hashCode());
			result = result * 31 + (this.clientData == null ? 0 : this.clientData.hashCode());
			return result;
		}
	}

	/**
	 * The user is typing a message.
	**/
	public static final class ChatActionTyping extends ChatAction {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 380122167;

		/**
		 * The user is typing a message.
		**/
		public ChatActionTyping() {}

		/**
		 * The user is typing a message.
		 *
		**/

		/**
		 * The user is typing a message.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatActionTyping(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatActionTyping.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatActionTyping.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ChatActionTyping.CONSTRUCTOR;
		}
	}

	/**
	 * The user is recording a video.
	**/
	public static final class ChatActionRecordingVideo extends ChatAction {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 216553362;

		/**
		 * The user is recording a video.
		**/
		public ChatActionRecordingVideo() {}

		/**
		 * The user is recording a video.
		 *
		**/

		/**
		 * The user is recording a video.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatActionRecordingVideo(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatActionRecordingVideo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatActionRecordingVideo.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ChatActionRecordingVideo.CONSTRUCTOR;
		}
	}

	/**
	 * The user is uploading a video.
	**/
	public static final class ChatActionUploadingVideo extends ChatAction {


		/**
		 * Upload progress, as a percentage.
		**/
		public int progress;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1234185270;

		/**
		 * The user is uploading a video.
		**/
		public ChatActionUploadingVideo() {}

		/**
		 * The user is uploading a video.
		 *
		 * @param progress Upload progress, as a percentage.
		**/
		public ChatActionUploadingVideo(int progress) {
			this.progress = progress;
		}

		/**
		 * The user is uploading a video.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatActionUploadingVideo(DataInput input) throws IOException {
			this.progress = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatActionUploadingVideo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatActionUploadingVideo.CONSTRUCTOR);
			output.writeInt(this.progress);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatActionUploadingVideo chatActionUploadingVideo = (ChatActionUploadingVideo) o;
			if (this.progress != chatActionUploadingVideo.progress) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.progress);
		}
	}

	/**
	 * The user is recording a voice note.
	**/
	public static final class ChatActionRecordingVoiceNote extends ChatAction {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -808850058;

		/**
		 * The user is recording a voice note.
		**/
		public ChatActionRecordingVoiceNote() {}

		/**
		 * The user is recording a voice note.
		 *
		**/

		/**
		 * The user is recording a voice note.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatActionRecordingVoiceNote(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatActionRecordingVoiceNote.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatActionRecordingVoiceNote.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ChatActionRecordingVoiceNote.CONSTRUCTOR;
		}
	}

	/**
	 * The user is uploading a voice note.
	**/
	public static final class ChatActionUploadingVoiceNote extends ChatAction {


		/**
		 * Upload progress, as a percentage.
		**/
		public int progress;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -613643666;

		/**
		 * The user is uploading a voice note.
		**/
		public ChatActionUploadingVoiceNote() {}

		/**
		 * The user is uploading a voice note.
		 *
		 * @param progress Upload progress, as a percentage.
		**/
		public ChatActionUploadingVoiceNote(int progress) {
			this.progress = progress;
		}

		/**
		 * The user is uploading a voice note.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatActionUploadingVoiceNote(DataInput input) throws IOException {
			this.progress = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatActionUploadingVoiceNote.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatActionUploadingVoiceNote.CONSTRUCTOR);
			output.writeInt(this.progress);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatActionUploadingVoiceNote chatActionUploadingVoiceNote = (ChatActionUploadingVoiceNote) o;
			if (this.progress != chatActionUploadingVoiceNote.progress) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.progress);
		}
	}

	/**
	 * The user is uploading a photo.
	**/
	public static final class ChatActionUploadingPhoto extends ChatAction {


		/**
		 * Upload progress, as a percentage.
		**/
		public int progress;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 654240583;

		/**
		 * The user is uploading a photo.
		**/
		public ChatActionUploadingPhoto() {}

		/**
		 * The user is uploading a photo.
		 *
		 * @param progress Upload progress, as a percentage.
		**/
		public ChatActionUploadingPhoto(int progress) {
			this.progress = progress;
		}

		/**
		 * The user is uploading a photo.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatActionUploadingPhoto(DataInput input) throws IOException {
			this.progress = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatActionUploadingPhoto.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatActionUploadingPhoto.CONSTRUCTOR);
			output.writeInt(this.progress);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatActionUploadingPhoto chatActionUploadingPhoto = (ChatActionUploadingPhoto) o;
			if (this.progress != chatActionUploadingPhoto.progress) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.progress);
		}
	}

	/**
	 * The user is uploading a document.
	**/
	public static final class ChatActionUploadingDocument extends ChatAction {


		/**
		 * Upload progress, as a percentage.
		**/
		public int progress;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 167884362;

		/**
		 * The user is uploading a document.
		**/
		public ChatActionUploadingDocument() {}

		/**
		 * The user is uploading a document.
		 *
		 * @param progress Upload progress, as a percentage.
		**/
		public ChatActionUploadingDocument(int progress) {
			this.progress = progress;
		}

		/**
		 * The user is uploading a document.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatActionUploadingDocument(DataInput input) throws IOException {
			this.progress = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatActionUploadingDocument.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatActionUploadingDocument.CONSTRUCTOR);
			output.writeInt(this.progress);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatActionUploadingDocument chatActionUploadingDocument = (ChatActionUploadingDocument) o;
			if (this.progress != chatActionUploadingDocument.progress) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.progress);
		}
	}

	/**
	 * The user is picking a sticker to send.
	**/
	public static final class ChatActionChoosingSticker extends ChatAction {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 372753697;

		/**
		 * The user is picking a sticker to send.
		**/
		public ChatActionChoosingSticker() {}

		/**
		 * The user is picking a sticker to send.
		 *
		**/

		/**
		 * The user is picking a sticker to send.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatActionChoosingSticker(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatActionChoosingSticker.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatActionChoosingSticker.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ChatActionChoosingSticker.CONSTRUCTOR;
		}
	}

	/**
	 * The user is picking a location or venue to send.
	**/
	public static final class ChatActionChoosingLocation extends ChatAction {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2017893596;

		/**
		 * The user is picking a location or venue to send.
		**/
		public ChatActionChoosingLocation() {}

		/**
		 * The user is picking a location or venue to send.
		 *
		**/

		/**
		 * The user is picking a location or venue to send.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatActionChoosingLocation(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatActionChoosingLocation.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatActionChoosingLocation.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ChatActionChoosingLocation.CONSTRUCTOR;
		}
	}

	/**
	 * The user is picking a contact to send.
	**/
	public static final class ChatActionChoosingContact extends ChatAction {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1222507496;

		/**
		 * The user is picking a contact to send.
		**/
		public ChatActionChoosingContact() {}

		/**
		 * The user is picking a contact to send.
		 *
		**/

		/**
		 * The user is picking a contact to send.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatActionChoosingContact(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatActionChoosingContact.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatActionChoosingContact.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ChatActionChoosingContact.CONSTRUCTOR;
		}
	}

	/**
	 * The user has started to play a game.
	**/
	public static final class ChatActionStartPlayingGame extends ChatAction {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -865884164;

		/**
		 * The user has started to play a game.
		**/
		public ChatActionStartPlayingGame() {}

		/**
		 * The user has started to play a game.
		 *
		**/

		/**
		 * The user has started to play a game.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatActionStartPlayingGame(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatActionStartPlayingGame.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatActionStartPlayingGame.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ChatActionStartPlayingGame.CONSTRUCTOR;
		}
	}

	/**
	 * The user is recording a video note.
	**/
	public static final class ChatActionRecordingVideoNote extends ChatAction {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 16523393;

		/**
		 * The user is recording a video note.
		**/
		public ChatActionRecordingVideoNote() {}

		/**
		 * The user is recording a video note.
		 *
		**/

		/**
		 * The user is recording a video note.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatActionRecordingVideoNote(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatActionRecordingVideoNote.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatActionRecordingVideoNote.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ChatActionRecordingVideoNote.CONSTRUCTOR;
		}
	}

	/**
	 * The user is uploading a video note.
	**/
	public static final class ChatActionUploadingVideoNote extends ChatAction {


		/**
		 * Upload progress, as a percentage.
		**/
		public int progress;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1172364918;

		/**
		 * The user is uploading a video note.
		**/
		public ChatActionUploadingVideoNote() {}

		/**
		 * The user is uploading a video note.
		 *
		 * @param progress Upload progress, as a percentage.
		**/
		public ChatActionUploadingVideoNote(int progress) {
			this.progress = progress;
		}

		/**
		 * The user is uploading a video note.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatActionUploadingVideoNote(DataInput input) throws IOException {
			this.progress = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatActionUploadingVideoNote.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatActionUploadingVideoNote.CONSTRUCTOR);
			output.writeInt(this.progress);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatActionUploadingVideoNote chatActionUploadingVideoNote = (ChatActionUploadingVideoNote) o;
			if (this.progress != chatActionUploadingVideoNote.progress) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.progress);
		}
	}

	/**
	 * The user is watching animations sent by the other party by clicking
	 * on an animated emoji.
	**/
	public static final class ChatActionWatchingAnimations extends ChatAction {


		/**
		 * The animated emoji.
		**/
		public String emoji;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2052990641;

		/**
		 * The user is watching animations sent by the other party by clicking on an animated emoji.
		**/
		public ChatActionWatchingAnimations() {}

		/**
		 * The user is watching animations sent by the other party by clicking on an animated emoji.
		 *
		 * @param emoji The animated emoji.
		**/
		public ChatActionWatchingAnimations(String emoji) {
			this.emoji = emoji;
		}

		/**
		 * The user is watching animations sent by the other party by clicking on an animated emoji.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatActionWatchingAnimations(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] emojiTmp = new byte[input.readInt()];
				input.readFully(emojiTmp);
				this.emoji = new String(emojiTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatActionWatchingAnimations.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatActionWatchingAnimations.CONSTRUCTOR);
			if (this.emoji == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] emojiTmp = this.emoji.getBytes(StandardCharsets.UTF_8);
				output.writeInt(emojiTmp.length);
				output.write(emojiTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatActionWatchingAnimations chatActionWatchingAnimations = (ChatActionWatchingAnimations) o;
			if (this.emoji != chatActionWatchingAnimations.emoji) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.emoji == null ? 0 : this.emoji.hashCode();
		}
	}

	/**
	 * The user has canceled the previous action.
	**/
	public static final class ChatActionCancel extends ChatAction {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1160523958;

		/**
		 * The user has canceled the previous action.
		**/
		public ChatActionCancel() {}

		/**
		 * The user has canceled the previous action.
		 *
		**/

		/**
		 * The user has canceled the previous action.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatActionCancel(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatActionCancel.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatActionCancel.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ChatActionCancel.CONSTRUCTOR;
		}
	}

	/**
	 * The chat can be reported as spam using the method reportChat with the
	 * reason chatReportReasonSpam. If the chat is a private chat with a
	 * user with an emoji status, then a notice about emoji status usage
	 * must be shown.
	**/
	public static final class ChatActionBarReportSpam extends ChatActionBar {


		/**
		 * If true, the chat was automatically archived and can be moved back to the main chat list using addChatToList simultaneously with setting chat notification settings to default using setChatNotificationSettings.
		**/
		public boolean canUnarchive;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1312758246;

		/**
		 * The chat can be reported as spam using the method reportChat with the reason chatReportReasonSpam. If the chat is a private chat with a user with an emoji status, then a notice about emoji status usage must be shown.
		**/
		public ChatActionBarReportSpam() {}

		/**
		 * The chat can be reported as spam using the method reportChat with the reason chatReportReasonSpam. If the chat is a private chat with a user with an emoji status, then a notice about emoji status usage must be shown.
		 *
		 * @param canUnarchive If true, the chat was automatically archived and can be moved back to the main chat list using addChatToList simultaneously with setting chat notification settings to default using setChatNotificationSettings.
		**/
		public ChatActionBarReportSpam(boolean canUnarchive) {
			this.canUnarchive = canUnarchive;
		}

		/**
		 * The chat can be reported as spam using the method reportChat with the reason chatReportReasonSpam. If the chat is a private chat with a user with an emoji status, then a notice about emoji status usage must be shown.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatActionBarReportSpam(DataInput input) throws IOException {
			this.canUnarchive = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatActionBarReportSpam.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatActionBarReportSpam.CONSTRUCTOR);
			output.writeBoolean(this.canUnarchive);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatActionBarReportSpam chatActionBarReportSpam = (ChatActionBarReportSpam) o;
			if (this.canUnarchive != chatActionBarReportSpam.canUnarchive) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Boolean.hashCode(this.canUnarchive);
		}
	}

	/**
	 * The chat is a location-based supergroup, which can be reported as
	 * having unrelated location using the method reportChat with the reason
	 * chatReportReasonUnrelatedLocation.
	**/
	public static final class ChatActionBarReportUnrelatedLocation extends ChatActionBar {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 758175489;

		/**
		 * The chat is a location-based supergroup, which can be reported as having unrelated location using the method reportChat with the reason chatReportReasonUnrelatedLocation.
		**/
		public ChatActionBarReportUnrelatedLocation() {}

		/**
		 * The chat is a location-based supergroup, which can be reported as having unrelated location using the method reportChat with the reason chatReportReasonUnrelatedLocation.
		 *
		**/

		/**
		 * The chat is a location-based supergroup, which can be reported as having unrelated location using the method reportChat with the reason chatReportReasonUnrelatedLocation.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatActionBarReportUnrelatedLocation(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatActionBarReportUnrelatedLocation.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatActionBarReportUnrelatedLocation.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ChatActionBarReportUnrelatedLocation.CONSTRUCTOR;
		}
	}

	/**
	 * The chat is a recently created group chat to which new members can be
	 * invited.
	**/
	public static final class ChatActionBarInviteMembers extends ChatActionBar {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1985313904;

		/**
		 * The chat is a recently created group chat to which new members can be invited.
		**/
		public ChatActionBarInviteMembers() {}

		/**
		 * The chat is a recently created group chat to which new members can be invited.
		 *
		**/

		/**
		 * The chat is a recently created group chat to which new members can be invited.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatActionBarInviteMembers(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatActionBarInviteMembers.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatActionBarInviteMembers.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ChatActionBarInviteMembers.CONSTRUCTOR;
		}
	}

	/**
	 * The chat is a private or secret chat, which can be reported using the
	 * method reportChat, or the other user can be blocked using the method
	 * toggleMessageSenderIsBlocked, or the other user can be added to the
	 * contact list using the method addContact. If the chat is a private
	 * chat with a user with an emoji status, then a notice about emoji
	 * status usage must be shown.
	**/
	public static final class ChatActionBarReportAddBlock extends ChatActionBar {


		/**
		 * If true, the chat was automatically archived and can be moved back to the main chat list using addChatToList simultaneously with setting chat notification settings to default using setChatNotificationSettings.
		**/
		public boolean canUnarchive;

		/**
		 * If non-negative, the current user was found by the peer through searchChatsNearby and this is the distance between the users.
		**/
		public int distance;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -914150419;

		/**
		 * The chat is a private or secret chat, which can be reported using the method reportChat, or the other user can be blocked using the method toggleMessageSenderIsBlocked, or the other user can be added to the contact list using the method addContact. If the chat is a private chat with a user with an emoji status, then a notice about emoji status usage must be shown.
		**/
		public ChatActionBarReportAddBlock() {}

		/**
		 * The chat is a private or secret chat, which can be reported using the method reportChat, or the other user can be blocked using the method toggleMessageSenderIsBlocked, or the other user can be added to the contact list using the method addContact. If the chat is a private chat with a user with an emoji status, then a notice about emoji status usage must be shown.
		 *
		 * @param canUnarchive If true, the chat was automatically archived and can be moved back to the main chat list using addChatToList simultaneously with setting chat notification settings to default using setChatNotificationSettings.
		 * @param distance If non-negative, the current user was found by the peer through searchChatsNearby and this is the distance between the users.
		**/
		public ChatActionBarReportAddBlock(boolean canUnarchive, int distance) {
			this.canUnarchive = canUnarchive;
			this.distance = distance;
		}

		/**
		 * The chat is a private or secret chat, which can be reported using the method reportChat, or the other user can be blocked using the method toggleMessageSenderIsBlocked, or the other user can be added to the contact list using the method addContact. If the chat is a private chat with a user with an emoji status, then a notice about emoji status usage must be shown.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatActionBarReportAddBlock(DataInput input) throws IOException {
			this.canUnarchive = input.readBoolean();
			this.distance = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatActionBarReportAddBlock.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatActionBarReportAddBlock.CONSTRUCTOR);
			output.writeBoolean(this.canUnarchive);
			output.writeInt(this.distance);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatActionBarReportAddBlock chatActionBarReportAddBlock = (ChatActionBarReportAddBlock) o;
			if (this.canUnarchive != chatActionBarReportAddBlock.canUnarchive) {
				return false;
			}
			if (this.distance != chatActionBarReportAddBlock.distance) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.canUnarchive);
			return result;
		}
	}

	/**
	 * The chat is a private or secret chat and the other user can be added
	 * to the contact list using the method addContact.
	**/
	public static final class ChatActionBarAddContact extends ChatActionBar {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -733325295;

		/**
		 * The chat is a private or secret chat and the other user can be added to the contact list using the method addContact.
		**/
		public ChatActionBarAddContact() {}

		/**
		 * The chat is a private or secret chat and the other user can be added to the contact list using the method addContact.
		 *
		**/

		/**
		 * The chat is a private or secret chat and the other user can be added to the contact list using the method addContact.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatActionBarAddContact(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatActionBarAddContact.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatActionBarAddContact.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ChatActionBarAddContact.CONSTRUCTOR;
		}
	}

	/**
	 * The chat is a private or secret chat with a mutual contact and the
	 * user&#039;s phone number can be shared with the other user using the
	 * method sharePhoneNumber.
	**/
	public static final class ChatActionBarSharePhoneNumber extends ChatActionBar {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 35188697;

		/**
		 * The chat is a private or secret chat with a mutual contact and the user&#039;s phone number can be shared with the other user using the method sharePhoneNumber.
		**/
		public ChatActionBarSharePhoneNumber() {}

		/**
		 * The chat is a private or secret chat with a mutual contact and the user&#039;s phone number can be shared with the other user using the method sharePhoneNumber.
		 *
		**/

		/**
		 * The chat is a private or secret chat with a mutual contact and the user&#039;s phone number can be shared with the other user using the method sharePhoneNumber.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatActionBarSharePhoneNumber(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatActionBarSharePhoneNumber.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatActionBarSharePhoneNumber.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ChatActionBarSharePhoneNumber.CONSTRUCTOR;
		}
	}

	/**
	 * The chat is a private chat with an administrator of a chat to which
	 * the user sent join request.
	**/
	public static final class ChatActionBarJoinRequest extends ChatActionBar {


		/**
		 * Title of the chat to which the join request was sent.
		**/
		public String title;

		/**
		 * True, if the join request was sent to a channel chat.
		**/
		public boolean isChannel;

		/**
		 * Point in time (Unix timestamp) when the join request was sent.
		**/
		public int requestDate;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1037140744;

		/**
		 * The chat is a private chat with an administrator of a chat to which the user sent join request.
		**/
		public ChatActionBarJoinRequest() {}

		/**
		 * The chat is a private chat with an administrator of a chat to which the user sent join request.
		 *
		 * @param title Title of the chat to which the join request was sent.
		 * @param isChannel True, if the join request was sent to a channel chat.
		 * @param requestDate Point in time (Unix timestamp) when the join request was sent.
		**/
		public ChatActionBarJoinRequest(String title, boolean isChannel, int requestDate) {
			this.title = title;
			this.isChannel = isChannel;
			this.requestDate = requestDate;
		}

		/**
		 * The chat is a private chat with an administrator of a chat to which the user sent join request.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatActionBarJoinRequest(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
			this.isChannel = input.readBoolean();
			this.requestDate = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatActionBarJoinRequest.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatActionBarJoinRequest.CONSTRUCTOR);
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
			output.writeBoolean(this.isChannel);
			output.writeInt(this.requestDate);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatActionBarJoinRequest chatActionBarJoinRequest = (ChatActionBarJoinRequest) o;
			if (this.title != chatActionBarJoinRequest.title) {
				return false;
			}
			if (this.isChannel != chatActionBarJoinRequest.isChannel) {
				return false;
			}
			if (this.requestDate != chatActionBarJoinRequest.requestDate) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isChannel);
			result = result * 31 + (this.title == null ? 0 : this.title.hashCode());
			return result;
		}
	}

	/**
	 * Contains information about a chat administrator.
	**/
	public static final class ChatAdministrator extends Object {


		/**
		 * User identifier of the administrator.
		**/
		public long userId;

		/**
		 * Custom title of the administrator.
		**/
		public String customTitle;

		/**
		 * True, if the user is the owner of the chat.
		**/
		public boolean isOwner;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1920449836;

		/**
		 * Contains information about a chat administrator.
		**/
		public ChatAdministrator() {}

		/**
		 * Contains information about a chat administrator.
		 *
		 * @param userId User identifier of the administrator.
		 * @param customTitle Custom title of the administrator.
		 * @param isOwner True, if the user is the owner of the chat.
		**/
		public ChatAdministrator(long userId, String customTitle, boolean isOwner) {
			this.userId = userId;
			this.customTitle = customTitle;
			this.isOwner = isOwner;
		}

		/**
		 * Contains information about a chat administrator.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatAdministrator(DataInput input) throws IOException {
			this.userId = input.readLong();
			if (input.readBoolean()) {
				byte[] customTitleTmp = new byte[input.readInt()];
				input.readFully(customTitleTmp);
				this.customTitle = new String(customTitleTmp, StandardCharsets.UTF_8);
			}
			this.isOwner = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatAdministrator.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatAdministrator.CONSTRUCTOR);
			output.writeLong(this.userId);
			if (this.customTitle == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] customTitleTmp = this.customTitle.getBytes(StandardCharsets.UTF_8);
				output.writeInt(customTitleTmp.length);
				output.write(customTitleTmp);
			}
			output.writeBoolean(this.isOwner);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatAdministrator chatAdministrator = (ChatAdministrator) o;
			if (this.userId != chatAdministrator.userId) {
				return false;
			}
			if (this.customTitle != chatAdministrator.customTitle) {
				return false;
			}
			if (this.isOwner != chatAdministrator.isOwner) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.userId);
			result = result * 31 + (this.customTitle == null ? 0 : this.customTitle.hashCode());
			return result;
		}
	}

	/**
	 * Describes rights of the administrator.
	**/
	public static final class ChatAdministratorRights extends Object {


		/**
		 * True, if the administrator can get chat event log, get chat statistics, get message statistics in channels, get channel members, see anonymous administrators in supergroups and ignore slow mode. Implied by any other privilege; applicable to supergroups and channels only.
		**/
		public boolean canManageChat;

		/**
		 * True, if the administrator can change the chat title, photo, and other settings.
		**/
		public boolean canChangeInfo;

		/**
		 * True, if the administrator can create channel posts; applicable to channels only.
		**/
		public boolean canPostMessages;

		/**
		 * True, if the administrator can edit messages of other users and pin messages; applicable to channels only.
		**/
		public boolean canEditMessages;

		/**
		 * True, if the administrator can delete messages of other users.
		**/
		public boolean canDeleteMessages;

		/**
		 * True, if the administrator can invite new users to the chat.
		**/
		public boolean canInviteUsers;

		/**
		 * True, if the administrator can restrict, ban, or unban chat members; always true for channels.
		**/
		public boolean canRestrictMembers;

		/**
		 * True, if the administrator can pin messages; applicable to basic groups and supergroups only.
		**/
		public boolean canPinMessages;

		/**
		 * True, if the administrator can manage topics; applicable to forum supergroups only.
		**/
		public boolean canManageTopics;

		/**
		 * True, if the administrator can add new administrators with a subset of their own privileges or demote administrators that were directly or indirectly promoted by them.
		**/
		public boolean canPromoteMembers;

		/**
		 * True, if the administrator can manage video chats.
		**/
		public boolean canManageVideoChats;

		/**
		 * True, if the administrator isn&#039;t shown in the chat member list and sends messages anonymously; applicable to supergroups only.
		**/
		public boolean isAnonymous;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1384650041;

		/**
		 * Describes rights of the administrator.
		**/
		public ChatAdministratorRights() {}

		/**
		 * Describes rights of the administrator.
		 *
		 * @param canManageChat True, if the administrator can get chat event log, get chat statistics, get message statistics in channels, get channel members, see anonymous administrators in supergroups and ignore slow mode. Implied by any other privilege; applicable to supergroups and channels only.
		 * @param canChangeInfo True, if the administrator can change the chat title, photo, and other settings.
		 * @param canPostMessages True, if the administrator can create channel posts; applicable to channels only.
		 * @param canEditMessages True, if the administrator can edit messages of other users and pin messages; applicable to channels only.
		 * @param canDeleteMessages True, if the administrator can delete messages of other users.
		 * @param canInviteUsers True, if the administrator can invite new users to the chat.
		 * @param canRestrictMembers True, if the administrator can restrict, ban, or unban chat members; always true for channels.
		 * @param canPinMessages True, if the administrator can pin messages; applicable to basic groups and supergroups only.
		 * @param canManageTopics True, if the administrator can manage topics; applicable to forum supergroups only.
		 * @param canPromoteMembers True, if the administrator can add new administrators with a subset of their own privileges or demote administrators that were directly or indirectly promoted by them.
		 * @param canManageVideoChats True, if the administrator can manage video chats.
		 * @param isAnonymous True, if the administrator isn&#039;t shown in the chat member list and sends messages anonymously; applicable to supergroups only.
		**/
		public ChatAdministratorRights(boolean canManageChat,
				boolean canChangeInfo,
				boolean canPostMessages,
				boolean canEditMessages,
				boolean canDeleteMessages,
				boolean canInviteUsers,
				boolean canRestrictMembers,
				boolean canPinMessages,
				boolean canManageTopics,
				boolean canPromoteMembers,
				boolean canManageVideoChats,
				boolean isAnonymous) {
			this.canManageChat = canManageChat;
			this.canChangeInfo = canChangeInfo;
			this.canPostMessages = canPostMessages;
			this.canEditMessages = canEditMessages;
			this.canDeleteMessages = canDeleteMessages;
			this.canInviteUsers = canInviteUsers;
			this.canRestrictMembers = canRestrictMembers;
			this.canPinMessages = canPinMessages;
			this.canManageTopics = canManageTopics;
			this.canPromoteMembers = canPromoteMembers;
			this.canManageVideoChats = canManageVideoChats;
			this.isAnonymous = isAnonymous;
		}

		/**
		 * Describes rights of the administrator.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatAdministratorRights(DataInput input) throws IOException {
			this.canManageChat = input.readBoolean();
			this.canChangeInfo = input.readBoolean();
			this.canPostMessages = input.readBoolean();
			this.canEditMessages = input.readBoolean();
			this.canDeleteMessages = input.readBoolean();
			this.canInviteUsers = input.readBoolean();
			this.canRestrictMembers = input.readBoolean();
			this.canPinMessages = input.readBoolean();
			this.canManageTopics = input.readBoolean();
			this.canPromoteMembers = input.readBoolean();
			this.canManageVideoChats = input.readBoolean();
			this.isAnonymous = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatAdministratorRights.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatAdministratorRights.CONSTRUCTOR);
			output.writeBoolean(this.canManageChat);
			output.writeBoolean(this.canChangeInfo);
			output.writeBoolean(this.canPostMessages);
			output.writeBoolean(this.canEditMessages);
			output.writeBoolean(this.canDeleteMessages);
			output.writeBoolean(this.canInviteUsers);
			output.writeBoolean(this.canRestrictMembers);
			output.writeBoolean(this.canPinMessages);
			output.writeBoolean(this.canManageTopics);
			output.writeBoolean(this.canPromoteMembers);
			output.writeBoolean(this.canManageVideoChats);
			output.writeBoolean(this.isAnonymous);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatAdministratorRights chatAdministratorRights = (ChatAdministratorRights) o;
			if (this.canManageChat != chatAdministratorRights.canManageChat) {
				return false;
			}
			if (this.canChangeInfo != chatAdministratorRights.canChangeInfo) {
				return false;
			}
			if (this.canPostMessages != chatAdministratorRights.canPostMessages) {
				return false;
			}
			if (this.canEditMessages != chatAdministratorRights.canEditMessages) {
				return false;
			}
			if (this.canDeleteMessages != chatAdministratorRights.canDeleteMessages) {
				return false;
			}
			if (this.canInviteUsers != chatAdministratorRights.canInviteUsers) {
				return false;
			}
			if (this.canRestrictMembers != chatAdministratorRights.canRestrictMembers) {
				return false;
			}
			if (this.canPinMessages != chatAdministratorRights.canPinMessages) {
				return false;
			}
			if (this.canManageTopics != chatAdministratorRights.canManageTopics) {
				return false;
			}
			if (this.canPromoteMembers != chatAdministratorRights.canPromoteMembers) {
				return false;
			}
			if (this.canManageVideoChats != chatAdministratorRights.canManageVideoChats) {
				return false;
			}
			if (this.isAnonymous != chatAdministratorRights.isAnonymous) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.canManageChat);
			return result;
		}
	}

	/**
	 * Represents a list of chat administrators.
	**/
	public static final class ChatAdministrators extends Object {


		/**
		 * A list of chat administrators.
		**/
		public ChatAdministrator[] administrators;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2126186435;

		/**
		 * Represents a list of chat administrators.
		**/
		public ChatAdministrators() {}

		/**
		 * Represents a list of chat administrators.
		 *
		 * @param administrators A list of chat administrators.
		**/
		public ChatAdministrators(ChatAdministrator[] administrators) {
			this.administrators = administrators;
		}

		/**
		 * Represents a list of chat administrators.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatAdministrators(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.administrators = new ChatAdministrator[input.readInt()];
				for (int i = 0; i < this.administrators.length; i++) {
					if (ChatAdministrator.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.administrators[i] = new ChatAdministrator(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatAdministrators.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatAdministrators.CONSTRUCTOR);
			if (this.administrators == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.administrators.length);
				for (int i = 0; i < this.administrators.length; i++) {
					this.administrators[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatAdministrators chatAdministrators = (ChatAdministrators) o;
			if (!Arrays.equals(this.administrators, chatAdministrators.administrators)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.administrators);
		}
	}

	/**
	 * All reactions are available in the chat.
	**/
	public static final class ChatAvailableReactionsAll extends ChatAvailableReactions {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -537887666;

		/**
		 * All reactions are available in the chat.
		**/
		public ChatAvailableReactionsAll() {}

		/**
		 * All reactions are available in the chat.
		 *
		**/

		/**
		 * All reactions are available in the chat.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatAvailableReactionsAll(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatAvailableReactionsAll.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatAvailableReactionsAll.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ChatAvailableReactionsAll.CONSTRUCTOR;
		}
	}

	/**
	 * Only specific reactions are available in the chat.
	**/
	public static final class ChatAvailableReactionsSome extends ChatAvailableReactions {


		/**
		 * The list of reactions.
		**/
		public ReactionType[] reactions;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -640810821;

		/**
		 * Only specific reactions are available in the chat.
		**/
		public ChatAvailableReactionsSome() {}

		/**
		 * Only specific reactions are available in the chat.
		 *
		 * @param reactions The list of reactions.
		**/
		public ChatAvailableReactionsSome(ReactionType[] reactions) {
			this.reactions = reactions;
		}

		/**
		 * Only specific reactions are available in the chat.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatAvailableReactionsSome(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.reactions = new ReactionType[input.readInt()];
				for (int i = 0; i < this.reactions.length; i++) {
					switch(input.readInt()) {
						case ReactionTypeEmoji.CONSTRUCTOR: this.reactions[i] = new ReactionTypeEmoji(input); break;
						case ReactionTypeCustomEmoji.CONSTRUCTOR: this.reactions[i] = new ReactionTypeCustomEmoji(input); break;
						default: {
							throw new UnsupportedOperationException();
						}
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatAvailableReactionsSome.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatAvailableReactionsSome.CONSTRUCTOR);
			if (this.reactions == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.reactions.length);
				for (int i = 0; i < this.reactions.length; i++) {
					this.reactions[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatAvailableReactionsSome chatAvailableReactionsSome = (ChatAvailableReactionsSome) o;
			if (!Arrays.equals(this.reactions, chatAvailableReactionsSome.reactions)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.reactions);
		}
	}

	/**
	 * Describes a background set for a specific chat.
	**/
	public static final class ChatBackground extends Object {


		/**
		 * The background.
		**/
		public Background background;

		/**
		 * Dimming of the background in dark themes, as a percentage; 0-100.
		**/
		public int darkThemeDimming;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1653152104;

		/**
		 * Describes a background set for a specific chat.
		**/
		public ChatBackground() {}

		/**
		 * Describes a background set for a specific chat.
		 *
		 * @param background The background.
		 * @param darkThemeDimming Dimming of the background in dark themes, as a percentage; 0-100.
		**/
		public ChatBackground(Background background, int darkThemeDimming) {
			this.background = background;
			this.darkThemeDimming = darkThemeDimming;
		}

		/**
		 * Describes a background set for a specific chat.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatBackground(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Background.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.background = new Background(input);
			}
			this.darkThemeDimming = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatBackground.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatBackground.CONSTRUCTOR);
			if (this.background == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.background.serialize(output);
			}
			output.writeInt(this.darkThemeDimming);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatBackground chatBackground = (ChatBackground) o;
			if (!Objects.equals(this.background, chatBackground.background)) {
				return false;
			}
			if (this.darkThemeDimming != chatBackground.darkThemeDimming) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.darkThemeDimming);
			result = result * 31 + (this.background == null ? 0 : this.background.hashCode());
			return result;
		}
	}

	/**
	 * Represents a chat event.
	**/
	public static final class ChatEvent extends Object {


		/**
		 * Chat event identifier.
		**/
		public long id;

		/**
		 * Point in time (Unix timestamp) when the event happened.
		**/
		public int date;

		/**
		 * Identifier of the user or chat who performed the action.
		**/
		public MessageSender memberId;

		/**
		 * The action.
		**/
		public ChatEventAction action;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -652102704;

		/**
		 * Represents a chat event.
		**/
		public ChatEvent() {}

		/**
		 * Represents a chat event.
		 *
		 * @param id Chat event identifier.
		 * @param date Point in time (Unix timestamp) when the event happened.
		 * @param memberId Identifier of the user or chat who performed the action.
		 * @param action The action.
		**/
		public ChatEvent(long id,
				int date,
				MessageSender memberId,
				ChatEventAction action) {
			this.id = id;
			this.date = date;
			this.memberId = memberId;
			this.action = action;
		}

		/**
		 * Represents a chat event.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatEvent(DataInput input) throws IOException {
			this.id = input.readLong();
			this.date = input.readInt();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case MessageSenderUser.CONSTRUCTOR: this.memberId = new MessageSenderUser(input); break;
					case MessageSenderChat.CONSTRUCTOR: this.memberId = new MessageSenderChat(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ChatEventMessageEdited.CONSTRUCTOR: this.action = new ChatEventMessageEdited(input); break;
					case ChatEventMessageDeleted.CONSTRUCTOR: this.action = new ChatEventMessageDeleted(input); break;
					case ChatEventMessagePinned.CONSTRUCTOR: this.action = new ChatEventMessagePinned(input); break;
					case ChatEventMessageUnpinned.CONSTRUCTOR: this.action = new ChatEventMessageUnpinned(input); break;
					case ChatEventPollStopped.CONSTRUCTOR: this.action = new ChatEventPollStopped(input); break;
					case ChatEventMemberJoined.CONSTRUCTOR: this.action = new ChatEventMemberJoined(input); break;
					case ChatEventMemberJoinedByInviteLink.CONSTRUCTOR: this.action = new ChatEventMemberJoinedByInviteLink(input); break;
					case ChatEventMemberJoinedByRequest.CONSTRUCTOR: this.action = new ChatEventMemberJoinedByRequest(input); break;
					case ChatEventMemberInvited.CONSTRUCTOR: this.action = new ChatEventMemberInvited(input); break;
					case ChatEventMemberLeft.CONSTRUCTOR: this.action = new ChatEventMemberLeft(input); break;
					case ChatEventMemberPromoted.CONSTRUCTOR: this.action = new ChatEventMemberPromoted(input); break;
					case ChatEventMemberRestricted.CONSTRUCTOR: this.action = new ChatEventMemberRestricted(input); break;
					case ChatEventAvailableReactionsChanged.CONSTRUCTOR: this.action = new ChatEventAvailableReactionsChanged(input); break;
					case ChatEventDescriptionChanged.CONSTRUCTOR: this.action = new ChatEventDescriptionChanged(input); break;
					case ChatEventLinkedChatChanged.CONSTRUCTOR: this.action = new ChatEventLinkedChatChanged(input); break;
					case ChatEventLocationChanged.CONSTRUCTOR: this.action = new ChatEventLocationChanged(input); break;
					case ChatEventMessageAutoDeleteTimeChanged.CONSTRUCTOR: this.action = new ChatEventMessageAutoDeleteTimeChanged(input); break;
					case ChatEventPermissionsChanged.CONSTRUCTOR: this.action = new ChatEventPermissionsChanged(input); break;
					case ChatEventPhotoChanged.CONSTRUCTOR: this.action = new ChatEventPhotoChanged(input); break;
					case ChatEventSlowModeDelayChanged.CONSTRUCTOR: this.action = new ChatEventSlowModeDelayChanged(input); break;
					case ChatEventStickerSetChanged.CONSTRUCTOR: this.action = new ChatEventStickerSetChanged(input); break;
					case ChatEventTitleChanged.CONSTRUCTOR: this.action = new ChatEventTitleChanged(input); break;
					case ChatEventUsernameChanged.CONSTRUCTOR: this.action = new ChatEventUsernameChanged(input); break;
					case ChatEventActiveUsernamesChanged.CONSTRUCTOR: this.action = new ChatEventActiveUsernamesChanged(input); break;
					case ChatEventHasProtectedContentToggled.CONSTRUCTOR: this.action = new ChatEventHasProtectedContentToggled(input); break;
					case ChatEventInvitesToggled.CONSTRUCTOR: this.action = new ChatEventInvitesToggled(input); break;
					case ChatEventIsAllHistoryAvailableToggled.CONSTRUCTOR: this.action = new ChatEventIsAllHistoryAvailableToggled(input); break;
					case ChatEventHasAggressiveAntiSpamEnabledToggled.CONSTRUCTOR: this.action = new ChatEventHasAggressiveAntiSpamEnabledToggled(input); break;
					case ChatEventSignMessagesToggled.CONSTRUCTOR: this.action = new ChatEventSignMessagesToggled(input); break;
					case ChatEventInviteLinkEdited.CONSTRUCTOR: this.action = new ChatEventInviteLinkEdited(input); break;
					case ChatEventInviteLinkRevoked.CONSTRUCTOR: this.action = new ChatEventInviteLinkRevoked(input); break;
					case ChatEventInviteLinkDeleted.CONSTRUCTOR: this.action = new ChatEventInviteLinkDeleted(input); break;
					case ChatEventVideoChatCreated.CONSTRUCTOR: this.action = new ChatEventVideoChatCreated(input); break;
					case ChatEventVideoChatEnded.CONSTRUCTOR: this.action = new ChatEventVideoChatEnded(input); break;
					case ChatEventVideoChatMuteNewParticipantsToggled.CONSTRUCTOR: this.action = new ChatEventVideoChatMuteNewParticipantsToggled(input); break;
					case ChatEventVideoChatParticipantIsMutedToggled.CONSTRUCTOR: this.action = new ChatEventVideoChatParticipantIsMutedToggled(input); break;
					case ChatEventVideoChatParticipantVolumeLevelChanged.CONSTRUCTOR: this.action = new ChatEventVideoChatParticipantVolumeLevelChanged(input); break;
					case ChatEventIsForumToggled.CONSTRUCTOR: this.action = new ChatEventIsForumToggled(input); break;
					case ChatEventForumTopicCreated.CONSTRUCTOR: this.action = new ChatEventForumTopicCreated(input); break;
					case ChatEventForumTopicEdited.CONSTRUCTOR: this.action = new ChatEventForumTopicEdited(input); break;
					case ChatEventForumTopicToggleIsClosed.CONSTRUCTOR: this.action = new ChatEventForumTopicToggleIsClosed(input); break;
					case ChatEventForumTopicToggleIsHidden.CONSTRUCTOR: this.action = new ChatEventForumTopicToggleIsHidden(input); break;
					case ChatEventForumTopicDeleted.CONSTRUCTOR: this.action = new ChatEventForumTopicDeleted(input); break;
					case ChatEventForumTopicPinned.CONSTRUCTOR: this.action = new ChatEventForumTopicPinned(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatEvent.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatEvent.CONSTRUCTOR);
			output.writeLong(this.id);
			output.writeInt(this.date);
			if (this.memberId == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.memberId.serialize(output);
			}
			if (this.action == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.action.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatEvent chatEvent = (ChatEvent) o;
			if (this.id != chatEvent.id) {
				return false;
			}
			if (this.date != chatEvent.date) {
				return false;
			}
			if (!Objects.equals(this.memberId, chatEvent.memberId)) {
				return false;
			}
			if (!Objects.equals(this.action, chatEvent.action)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.id);
			result = result * 31 + (this.memberId == null ? 0 : this.memberId.hashCode());
			result = result * 31 + (this.action == null ? 0 : this.action.hashCode());
			return result;
		}
	}

	/**
	 * A message was edited.
	**/
	public static final class ChatEventMessageEdited extends ChatEventAction {


		/**
		 * The original message before the edit.
		**/
		public Message oldMessage;

		/**
		 * The message after it was edited.
		**/
		public Message newMessage;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -430967304;

		/**
		 * A message was edited.
		**/
		public ChatEventMessageEdited() {}

		/**
		 * A message was edited.
		 *
		 * @param oldMessage The original message before the edit.
		 * @param newMessage The message after it was edited.
		**/
		public ChatEventMessageEdited(Message oldMessage, Message newMessage) {
			this.oldMessage = oldMessage;
			this.newMessage = newMessage;
		}

		/**
		 * A message was edited.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatEventMessageEdited(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Message.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.oldMessage = new Message(input);
			}
			if (input.readBoolean()) {
				if (Message.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.newMessage = new Message(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatEventMessageEdited.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatEventMessageEdited.CONSTRUCTOR);
			if (this.oldMessage == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.oldMessage.serialize(output);
			}
			if (this.newMessage == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.newMessage.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatEventMessageEdited chatEventMessageEdited = (ChatEventMessageEdited) o;
			if (!Objects.equals(this.oldMessage, chatEventMessageEdited.oldMessage)) {
				return false;
			}
			if (!Objects.equals(this.newMessage, chatEventMessageEdited.newMessage)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.oldMessage == null ? 0 : this.oldMessage.hashCode();
			result = result * 31 + (this.newMessage == null ? 0 : this.newMessage.hashCode());
			return result;
		}
	}

	/**
	 * A message was deleted.
	**/
	public static final class ChatEventMessageDeleted extends ChatEventAction {


		/**
		 * Deleted message.
		**/
		public Message message;

		/**
		 * True, if the message deletion can be reported via reportSupergroupAntiSpamFalsePositive.
		**/
		public boolean canReportAntiSpamFalsePositive;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 935316851;

		/**
		 * A message was deleted.
		**/
		public ChatEventMessageDeleted() {}

		/**
		 * A message was deleted.
		 *
		 * @param message Deleted message.
		 * @param canReportAntiSpamFalsePositive True, if the message deletion can be reported via reportSupergroupAntiSpamFalsePositive.
		**/
		public ChatEventMessageDeleted(Message message, boolean canReportAntiSpamFalsePositive) {
			this.message = message;
			this.canReportAntiSpamFalsePositive = canReportAntiSpamFalsePositive;
		}

		/**
		 * A message was deleted.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatEventMessageDeleted(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Message.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.message = new Message(input);
			}
			this.canReportAntiSpamFalsePositive = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatEventMessageDeleted.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatEventMessageDeleted.CONSTRUCTOR);
			if (this.message == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.message.serialize(output);
			}
			output.writeBoolean(this.canReportAntiSpamFalsePositive);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatEventMessageDeleted chatEventMessageDeleted = (ChatEventMessageDeleted) o;
			if (!Objects.equals(this.message, chatEventMessageDeleted.message)) {
				return false;
			}
			if (this.canReportAntiSpamFalsePositive != chatEventMessageDeleted.canReportAntiSpamFalsePositive) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.canReportAntiSpamFalsePositive);
			result = result * 31 + (this.message == null ? 0 : this.message.hashCode());
			return result;
		}
	}

	/**
	 * A message was pinned.
	**/
	public static final class ChatEventMessagePinned extends ChatEventAction {


		/**
		 * Pinned message.
		**/
		public Message message;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 438742298;

		/**
		 * A message was pinned.
		**/
		public ChatEventMessagePinned() {}

		/**
		 * A message was pinned.
		 *
		 * @param message Pinned message.
		**/
		public ChatEventMessagePinned(Message message) {
			this.message = message;
		}

		/**
		 * A message was pinned.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatEventMessagePinned(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Message.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.message = new Message(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatEventMessagePinned.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatEventMessagePinned.CONSTRUCTOR);
			if (this.message == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.message.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatEventMessagePinned chatEventMessagePinned = (ChatEventMessagePinned) o;
			if (!Objects.equals(this.message, chatEventMessagePinned.message)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.message == null ? 0 : this.message.hashCode();
		}
	}

	/**
	 * A message was unpinned.
	**/
	public static final class ChatEventMessageUnpinned extends ChatEventAction {


		/**
		 * Unpinned message.
		**/
		public Message message;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -376161513;

		/**
		 * A message was unpinned.
		**/
		public ChatEventMessageUnpinned() {}

		/**
		 * A message was unpinned.
		 *
		 * @param message Unpinned message.
		**/
		public ChatEventMessageUnpinned(Message message) {
			this.message = message;
		}

		/**
		 * A message was unpinned.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatEventMessageUnpinned(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Message.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.message = new Message(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatEventMessageUnpinned.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatEventMessageUnpinned.CONSTRUCTOR);
			if (this.message == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.message.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatEventMessageUnpinned chatEventMessageUnpinned = (ChatEventMessageUnpinned) o;
			if (!Objects.equals(this.message, chatEventMessageUnpinned.message)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.message == null ? 0 : this.message.hashCode();
		}
	}

	/**
	 * A poll in a message was stopped.
	**/
	public static final class ChatEventPollStopped extends ChatEventAction {


		/**
		 * The message with the poll.
		**/
		public Message message;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2009893861;

		/**
		 * A poll in a message was stopped.
		**/
		public ChatEventPollStopped() {}

		/**
		 * A poll in a message was stopped.
		 *
		 * @param message The message with the poll.
		**/
		public ChatEventPollStopped(Message message) {
			this.message = message;
		}

		/**
		 * A poll in a message was stopped.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatEventPollStopped(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Message.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.message = new Message(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatEventPollStopped.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatEventPollStopped.CONSTRUCTOR);
			if (this.message == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.message.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatEventPollStopped chatEventPollStopped = (ChatEventPollStopped) o;
			if (!Objects.equals(this.message, chatEventPollStopped.message)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.message == null ? 0 : this.message.hashCode();
		}
	}

	/**
	 * A new member joined the chat.
	**/
	public static final class ChatEventMemberJoined extends ChatEventAction {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -235468508;

		/**
		 * A new member joined the chat.
		**/
		public ChatEventMemberJoined() {}

		/**
		 * A new member joined the chat.
		 *
		**/

		/**
		 * A new member joined the chat.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatEventMemberJoined(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatEventMemberJoined.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatEventMemberJoined.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ChatEventMemberJoined.CONSTRUCTOR;
		}
	}

	/**
	 * A new member joined the chat via an invite link.
	**/
	public static final class ChatEventMemberJoinedByInviteLink extends ChatEventAction {


		/**
		 * Invite link used to join the chat.
		**/
		public ChatInviteLink inviteLink;

		/**
		 * True, if the user has joined the chat using an invite link for a chat folder.
		**/
		public boolean viaChatFolderInviteLink;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1445536390;

		/**
		 * A new member joined the chat via an invite link.
		**/
		public ChatEventMemberJoinedByInviteLink() {}

		/**
		 * A new member joined the chat via an invite link.
		 *
		 * @param inviteLink Invite link used to join the chat.
		 * @param viaChatFolderInviteLink True, if the user has joined the chat using an invite link for a chat folder.
		**/
		public ChatEventMemberJoinedByInviteLink(ChatInviteLink inviteLink, boolean viaChatFolderInviteLink) {
			this.inviteLink = inviteLink;
			this.viaChatFolderInviteLink = viaChatFolderInviteLink;
		}

		/**
		 * A new member joined the chat via an invite link.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatEventMemberJoinedByInviteLink(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (ChatInviteLink.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.inviteLink = new ChatInviteLink(input);
			}
			this.viaChatFolderInviteLink = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatEventMemberJoinedByInviteLink.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatEventMemberJoinedByInviteLink.CONSTRUCTOR);
			if (this.inviteLink == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.inviteLink.serialize(output);
			}
			output.writeBoolean(this.viaChatFolderInviteLink);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatEventMemberJoinedByInviteLink chatEventMemberJoinedByInviteLink = (ChatEventMemberJoinedByInviteLink) o;
			if (!Objects.equals(this.inviteLink, chatEventMemberJoinedByInviteLink.inviteLink)) {
				return false;
			}
			if (this.viaChatFolderInviteLink != chatEventMemberJoinedByInviteLink.viaChatFolderInviteLink) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.viaChatFolderInviteLink);
			result = result * 31 + (this.inviteLink == null ? 0 : this.inviteLink.hashCode());
			return result;
		}
	}

	/**
	 * A new member was accepted to the chat by an administrator.
	**/
	public static final class ChatEventMemberJoinedByRequest extends ChatEventAction {


		/**
		 * User identifier of the chat administrator, approved user join request.
		**/
		public long approverUserId;

		/**
		 * Invite link used to join the chat; may be null.
		**/
		public ChatInviteLink inviteLink;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1647804865;

		/**
		 * A new member was accepted to the chat by an administrator.
		**/
		public ChatEventMemberJoinedByRequest() {}

		/**
		 * A new member was accepted to the chat by an administrator.
		 *
		 * @param approverUserId User identifier of the chat administrator, approved user join request.
		 * @param inviteLink Invite link used to join the chat; may be null.
		**/
		public ChatEventMemberJoinedByRequest(long approverUserId, ChatInviteLink inviteLink) {
			this.approverUserId = approverUserId;
			this.inviteLink = inviteLink;
		}

		/**
		 * A new member was accepted to the chat by an administrator.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatEventMemberJoinedByRequest(DataInput input) throws IOException {
			this.approverUserId = input.readLong();
			if (input.readBoolean()) {
				if (ChatInviteLink.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.inviteLink = new ChatInviteLink(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatEventMemberJoinedByRequest.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatEventMemberJoinedByRequest.CONSTRUCTOR);
			output.writeLong(this.approverUserId);
			if (this.inviteLink == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.inviteLink.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatEventMemberJoinedByRequest chatEventMemberJoinedByRequest = (ChatEventMemberJoinedByRequest) o;
			if (this.approverUserId != chatEventMemberJoinedByRequest.approverUserId) {
				return false;
			}
			if (!Objects.equals(this.inviteLink, chatEventMemberJoinedByRequest.inviteLink)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.approverUserId);
			result = result * 31 + (this.inviteLink == null ? 0 : this.inviteLink.hashCode());
			return result;
		}
	}

	/**
	 * A new chat member was invited.
	**/
	public static final class ChatEventMemberInvited extends ChatEventAction {


		/**
		 * New member user identifier.
		**/
		public long userId;

		/**
		 * New member status.
		**/
		public ChatMemberStatus status;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 953663433;

		/**
		 * A new chat member was invited.
		**/
		public ChatEventMemberInvited() {}

		/**
		 * A new chat member was invited.
		 *
		 * @param userId New member user identifier.
		 * @param status New member status.
		**/
		public ChatEventMemberInvited(long userId, ChatMemberStatus status) {
			this.userId = userId;
			this.status = status;
		}

		/**
		 * A new chat member was invited.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatEventMemberInvited(DataInput input) throws IOException {
			this.userId = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ChatMemberStatusCreator.CONSTRUCTOR: this.status = new ChatMemberStatusCreator(input); break;
					case ChatMemberStatusAdministrator.CONSTRUCTOR: this.status = new ChatMemberStatusAdministrator(input); break;
					case ChatMemberStatusMember.CONSTRUCTOR: this.status = new ChatMemberStatusMember(input); break;
					case ChatMemberStatusRestricted.CONSTRUCTOR: this.status = new ChatMemberStatusRestricted(input); break;
					case ChatMemberStatusLeft.CONSTRUCTOR: this.status = new ChatMemberStatusLeft(input); break;
					case ChatMemberStatusBanned.CONSTRUCTOR: this.status = new ChatMemberStatusBanned(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatEventMemberInvited.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatEventMemberInvited.CONSTRUCTOR);
			output.writeLong(this.userId);
			if (this.status == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.status.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatEventMemberInvited chatEventMemberInvited = (ChatEventMemberInvited) o;
			if (this.userId != chatEventMemberInvited.userId) {
				return false;
			}
			if (!Objects.equals(this.status, chatEventMemberInvited.status)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.userId);
			result = result * 31 + (this.status == null ? 0 : this.status.hashCode());
			return result;
		}
	}

	/**
	 * A member left the chat.
	**/
	public static final class ChatEventMemberLeft extends ChatEventAction {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -948420593;

		/**
		 * A member left the chat.
		**/
		public ChatEventMemberLeft() {}

		/**
		 * A member left the chat.
		 *
		**/

		/**
		 * A member left the chat.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatEventMemberLeft(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatEventMemberLeft.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatEventMemberLeft.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ChatEventMemberLeft.CONSTRUCTOR;
		}
	}

	/**
	 * A chat member has gained/lost administrator status, or the list of
	 * their administrator privileges has changed.
	**/
	public static final class ChatEventMemberPromoted extends ChatEventAction {


		/**
		 * Affected chat member user identifier.
		**/
		public long userId;

		/**
		 * Previous status of the chat member.
		**/
		public ChatMemberStatus oldStatus;

		/**
		 * New status of the chat member.
		**/
		public ChatMemberStatus newStatus;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 525297761;

		/**
		 * A chat member has gained/lost administrator status, or the list of their administrator privileges has changed.
		**/
		public ChatEventMemberPromoted() {}

		/**
		 * A chat member has gained/lost administrator status, or the list of their administrator privileges has changed.
		 *
		 * @param userId Affected chat member user identifier.
		 * @param oldStatus Previous status of the chat member.
		 * @param newStatus New status of the chat member.
		**/
		public ChatEventMemberPromoted(long userId,
				ChatMemberStatus oldStatus,
				ChatMemberStatus newStatus) {
			this.userId = userId;
			this.oldStatus = oldStatus;
			this.newStatus = newStatus;
		}

		/**
		 * A chat member has gained/lost administrator status, or the list of their administrator privileges has changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatEventMemberPromoted(DataInput input) throws IOException {
			this.userId = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ChatMemberStatusCreator.CONSTRUCTOR: this.oldStatus = new ChatMemberStatusCreator(input); break;
					case ChatMemberStatusAdministrator.CONSTRUCTOR: this.oldStatus = new ChatMemberStatusAdministrator(input); break;
					case ChatMemberStatusMember.CONSTRUCTOR: this.oldStatus = new ChatMemberStatusMember(input); break;
					case ChatMemberStatusRestricted.CONSTRUCTOR: this.oldStatus = new ChatMemberStatusRestricted(input); break;
					case ChatMemberStatusLeft.CONSTRUCTOR: this.oldStatus = new ChatMemberStatusLeft(input); break;
					case ChatMemberStatusBanned.CONSTRUCTOR: this.oldStatus = new ChatMemberStatusBanned(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ChatMemberStatusCreator.CONSTRUCTOR: this.newStatus = new ChatMemberStatusCreator(input); break;
					case ChatMemberStatusAdministrator.CONSTRUCTOR: this.newStatus = new ChatMemberStatusAdministrator(input); break;
					case ChatMemberStatusMember.CONSTRUCTOR: this.newStatus = new ChatMemberStatusMember(input); break;
					case ChatMemberStatusRestricted.CONSTRUCTOR: this.newStatus = new ChatMemberStatusRestricted(input); break;
					case ChatMemberStatusLeft.CONSTRUCTOR: this.newStatus = new ChatMemberStatusLeft(input); break;
					case ChatMemberStatusBanned.CONSTRUCTOR: this.newStatus = new ChatMemberStatusBanned(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatEventMemberPromoted.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatEventMemberPromoted.CONSTRUCTOR);
			output.writeLong(this.userId);
			if (this.oldStatus == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.oldStatus.serialize(output);
			}
			if (this.newStatus == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.newStatus.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatEventMemberPromoted chatEventMemberPromoted = (ChatEventMemberPromoted) o;
			if (this.userId != chatEventMemberPromoted.userId) {
				return false;
			}
			if (!Objects.equals(this.oldStatus, chatEventMemberPromoted.oldStatus)) {
				return false;
			}
			if (!Objects.equals(this.newStatus, chatEventMemberPromoted.newStatus)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.userId);
			result = result * 31 + (this.oldStatus == null ? 0 : this.oldStatus.hashCode());
			result = result * 31 + (this.newStatus == null ? 0 : this.newStatus.hashCode());
			return result;
		}
	}

	/**
	 * A chat member was restricted/unrestricted or banned/unbanned, or the
	 * list of their restrictions has changed.
	**/
	public static final class ChatEventMemberRestricted extends ChatEventAction {


		/**
		 * Affected chat member identifier.
		**/
		public MessageSender memberId;

		/**
		 * Previous status of the chat member.
		**/
		public ChatMemberStatus oldStatus;

		/**
		 * New status of the chat member.
		**/
		public ChatMemberStatus newStatus;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1603608069;

		/**
		 * A chat member was restricted/unrestricted or banned/unbanned, or the list of their restrictions has changed.
		**/
		public ChatEventMemberRestricted() {}

		/**
		 * A chat member was restricted/unrestricted or banned/unbanned, or the list of their restrictions has changed.
		 *
		 * @param memberId Affected chat member identifier.
		 * @param oldStatus Previous status of the chat member.
		 * @param newStatus New status of the chat member.
		**/
		public ChatEventMemberRestricted(MessageSender memberId,
				ChatMemberStatus oldStatus,
				ChatMemberStatus newStatus) {
			this.memberId = memberId;
			this.oldStatus = oldStatus;
			this.newStatus = newStatus;
		}

		/**
		 * A chat member was restricted/unrestricted or banned/unbanned, or the list of their restrictions has changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatEventMemberRestricted(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case MessageSenderUser.CONSTRUCTOR: this.memberId = new MessageSenderUser(input); break;
					case MessageSenderChat.CONSTRUCTOR: this.memberId = new MessageSenderChat(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ChatMemberStatusCreator.CONSTRUCTOR: this.oldStatus = new ChatMemberStatusCreator(input); break;
					case ChatMemberStatusAdministrator.CONSTRUCTOR: this.oldStatus = new ChatMemberStatusAdministrator(input); break;
					case ChatMemberStatusMember.CONSTRUCTOR: this.oldStatus = new ChatMemberStatusMember(input); break;
					case ChatMemberStatusRestricted.CONSTRUCTOR: this.oldStatus = new ChatMemberStatusRestricted(input); break;
					case ChatMemberStatusLeft.CONSTRUCTOR: this.oldStatus = new ChatMemberStatusLeft(input); break;
					case ChatMemberStatusBanned.CONSTRUCTOR: this.oldStatus = new ChatMemberStatusBanned(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ChatMemberStatusCreator.CONSTRUCTOR: this.newStatus = new ChatMemberStatusCreator(input); break;
					case ChatMemberStatusAdministrator.CONSTRUCTOR: this.newStatus = new ChatMemberStatusAdministrator(input); break;
					case ChatMemberStatusMember.CONSTRUCTOR: this.newStatus = new ChatMemberStatusMember(input); break;
					case ChatMemberStatusRestricted.CONSTRUCTOR: this.newStatus = new ChatMemberStatusRestricted(input); break;
					case ChatMemberStatusLeft.CONSTRUCTOR: this.newStatus = new ChatMemberStatusLeft(input); break;
					case ChatMemberStatusBanned.CONSTRUCTOR: this.newStatus = new ChatMemberStatusBanned(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatEventMemberRestricted.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatEventMemberRestricted.CONSTRUCTOR);
			if (this.memberId == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.memberId.serialize(output);
			}
			if (this.oldStatus == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.oldStatus.serialize(output);
			}
			if (this.newStatus == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.newStatus.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatEventMemberRestricted chatEventMemberRestricted = (ChatEventMemberRestricted) o;
			if (!Objects.equals(this.memberId, chatEventMemberRestricted.memberId)) {
				return false;
			}
			if (!Objects.equals(this.oldStatus, chatEventMemberRestricted.oldStatus)) {
				return false;
			}
			if (!Objects.equals(this.newStatus, chatEventMemberRestricted.newStatus)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.memberId == null ? 0 : this.memberId.hashCode();
			result = result * 31 + (this.oldStatus == null ? 0 : this.oldStatus.hashCode());
			result = result * 31 + (this.newStatus == null ? 0 : this.newStatus.hashCode());
			return result;
		}
	}

	/**
	 * The chat available reactions were changed.
	**/
	public static final class ChatEventAvailableReactionsChanged extends ChatEventAction {


		/**
		 * Previous chat available reactions.
		**/
		public ChatAvailableReactions oldAvailableReactions;

		/**
		 * New chat available reactions.
		**/
		public ChatAvailableReactions newAvailableReactions;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1749491521;

		/**
		 * The chat available reactions were changed.
		**/
		public ChatEventAvailableReactionsChanged() {}

		/**
		 * The chat available reactions were changed.
		 *
		 * @param oldAvailableReactions Previous chat available reactions.
		 * @param newAvailableReactions New chat available reactions.
		**/
		public ChatEventAvailableReactionsChanged(ChatAvailableReactions oldAvailableReactions,
				ChatAvailableReactions newAvailableReactions) {
			this.oldAvailableReactions = oldAvailableReactions;
			this.newAvailableReactions = newAvailableReactions;
		}

		/**
		 * The chat available reactions were changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatEventAvailableReactionsChanged(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ChatAvailableReactionsAll.CONSTRUCTOR: this.oldAvailableReactions = new ChatAvailableReactionsAll(input); break;
					case ChatAvailableReactionsSome.CONSTRUCTOR: this.oldAvailableReactions = new ChatAvailableReactionsSome(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ChatAvailableReactionsAll.CONSTRUCTOR: this.newAvailableReactions = new ChatAvailableReactionsAll(input); break;
					case ChatAvailableReactionsSome.CONSTRUCTOR: this.newAvailableReactions = new ChatAvailableReactionsSome(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatEventAvailableReactionsChanged.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatEventAvailableReactionsChanged.CONSTRUCTOR);
			if (this.oldAvailableReactions == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.oldAvailableReactions.serialize(output);
			}
			if (this.newAvailableReactions == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.newAvailableReactions.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatEventAvailableReactionsChanged chatEventAvailableReactionsChanged = (ChatEventAvailableReactionsChanged) o;
			if (!Objects.equals(this.oldAvailableReactions, chatEventAvailableReactionsChanged.oldAvailableReactions)) {
				return false;
			}
			if (!Objects.equals(this.newAvailableReactions, chatEventAvailableReactionsChanged.newAvailableReactions)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.oldAvailableReactions == null ? 0 : this.oldAvailableReactions.hashCode();
			result = result * 31 + (this.newAvailableReactions == null ? 0 : this.newAvailableReactions.hashCode());
			return result;
		}
	}

	/**
	 * The chat description was changed.
	**/
	public static final class ChatEventDescriptionChanged extends ChatEventAction {


		/**
		 * Previous chat description.
		**/
		public String oldDescription;

		/**
		 * New chat description.
		**/
		public String newDescription;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 39112478;

		/**
		 * The chat description was changed.
		**/
		public ChatEventDescriptionChanged() {}

		/**
		 * The chat description was changed.
		 *
		 * @param oldDescription Previous chat description.
		 * @param newDescription New chat description.
		**/
		public ChatEventDescriptionChanged(String oldDescription, String newDescription) {
			this.oldDescription = oldDescription;
			this.newDescription = newDescription;
		}

		/**
		 * The chat description was changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatEventDescriptionChanged(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] oldDescriptionTmp = new byte[input.readInt()];
				input.readFully(oldDescriptionTmp);
				this.oldDescription = new String(oldDescriptionTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] newDescriptionTmp = new byte[input.readInt()];
				input.readFully(newDescriptionTmp);
				this.newDescription = new String(newDescriptionTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatEventDescriptionChanged.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatEventDescriptionChanged.CONSTRUCTOR);
			if (this.oldDescription == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] oldDescriptionTmp = this.oldDescription.getBytes(StandardCharsets.UTF_8);
				output.writeInt(oldDescriptionTmp.length);
				output.write(oldDescriptionTmp);
			}
			if (this.newDescription == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] newDescriptionTmp = this.newDescription.getBytes(StandardCharsets.UTF_8);
				output.writeInt(newDescriptionTmp.length);
				output.write(newDescriptionTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatEventDescriptionChanged chatEventDescriptionChanged = (ChatEventDescriptionChanged) o;
			if (this.oldDescription != chatEventDescriptionChanged.oldDescription) {
				return false;
			}
			if (this.newDescription != chatEventDescriptionChanged.newDescription) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.oldDescription == null ? 0 : this.oldDescription.hashCode();
			result = result * 31 + (this.newDescription == null ? 0 : this.newDescription.hashCode());
			return result;
		}
	}

	/**
	 * The linked chat of a supergroup was changed.
	**/
	public static final class ChatEventLinkedChatChanged extends ChatEventAction {


		/**
		 * Previous supergroup linked chat identifier.
		**/
		public long oldLinkedChatId;

		/**
		 * New supergroup linked chat identifier.
		**/
		public long newLinkedChatId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1797419439;

		/**
		 * The linked chat of a supergroup was changed.
		**/
		public ChatEventLinkedChatChanged() {}

		/**
		 * The linked chat of a supergroup was changed.
		 *
		 * @param oldLinkedChatId Previous supergroup linked chat identifier.
		 * @param newLinkedChatId New supergroup linked chat identifier.
		**/
		public ChatEventLinkedChatChanged(long oldLinkedChatId, long newLinkedChatId) {
			this.oldLinkedChatId = oldLinkedChatId;
			this.newLinkedChatId = newLinkedChatId;
		}

		/**
		 * The linked chat of a supergroup was changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatEventLinkedChatChanged(DataInput input) throws IOException {
			this.oldLinkedChatId = input.readLong();
			this.newLinkedChatId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatEventLinkedChatChanged.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatEventLinkedChatChanged.CONSTRUCTOR);
			output.writeLong(this.oldLinkedChatId);
			output.writeLong(this.newLinkedChatId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatEventLinkedChatChanged chatEventLinkedChatChanged = (ChatEventLinkedChatChanged) o;
			if (this.oldLinkedChatId != chatEventLinkedChatChanged.oldLinkedChatId) {
				return false;
			}
			if (this.newLinkedChatId != chatEventLinkedChatChanged.newLinkedChatId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.oldLinkedChatId);
			return result;
		}
	}

	/**
	 * The supergroup location was changed.
	**/
	public static final class ChatEventLocationChanged extends ChatEventAction {


		/**
		 * Previous location; may be null.
		**/
		public ChatLocation oldLocation;

		/**
		 * New location; may be null.
		**/
		public ChatLocation newLocation;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -405930674;

		/**
		 * The supergroup location was changed.
		**/
		public ChatEventLocationChanged() {}

		/**
		 * The supergroup location was changed.
		 *
		 * @param oldLocation Previous location; may be null.
		 * @param newLocation New location; may be null.
		**/
		public ChatEventLocationChanged(ChatLocation oldLocation, ChatLocation newLocation) {
			this.oldLocation = oldLocation;
			this.newLocation = newLocation;
		}

		/**
		 * The supergroup location was changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatEventLocationChanged(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (ChatLocation.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.oldLocation = new ChatLocation(input);
			}
			if (input.readBoolean()) {
				if (ChatLocation.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.newLocation = new ChatLocation(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatEventLocationChanged.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatEventLocationChanged.CONSTRUCTOR);
			if (this.oldLocation == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.oldLocation.serialize(output);
			}
			if (this.newLocation == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.newLocation.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatEventLocationChanged chatEventLocationChanged = (ChatEventLocationChanged) o;
			if (!Objects.equals(this.oldLocation, chatEventLocationChanged.oldLocation)) {
				return false;
			}
			if (!Objects.equals(this.newLocation, chatEventLocationChanged.newLocation)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.oldLocation == null ? 0 : this.oldLocation.hashCode();
			result = result * 31 + (this.newLocation == null ? 0 : this.newLocation.hashCode());
			return result;
		}
	}

	/**
	 * The message auto-delete timer was changed.
	**/
	public static final class ChatEventMessageAutoDeleteTimeChanged extends ChatEventAction {


		/**
		 * Previous value of messageAutoDeleteTime.
		**/
		public int oldMessageAutoDeleteTime;

		/**
		 * New value of messageAutoDeleteTime.
		**/
		public int newMessageAutoDeleteTime;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 17317668;

		/**
		 * The message auto-delete timer was changed.
		**/
		public ChatEventMessageAutoDeleteTimeChanged() {}

		/**
		 * The message auto-delete timer was changed.
		 *
		 * @param oldMessageAutoDeleteTime Previous value of messageAutoDeleteTime.
		 * @param newMessageAutoDeleteTime New value of messageAutoDeleteTime.
		**/
		public ChatEventMessageAutoDeleteTimeChanged(int oldMessageAutoDeleteTime, int newMessageAutoDeleteTime) {
			this.oldMessageAutoDeleteTime = oldMessageAutoDeleteTime;
			this.newMessageAutoDeleteTime = newMessageAutoDeleteTime;
		}

		/**
		 * The message auto-delete timer was changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatEventMessageAutoDeleteTimeChanged(DataInput input) throws IOException {
			this.oldMessageAutoDeleteTime = input.readInt();
			this.newMessageAutoDeleteTime = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatEventMessageAutoDeleteTimeChanged.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatEventMessageAutoDeleteTimeChanged.CONSTRUCTOR);
			output.writeInt(this.oldMessageAutoDeleteTime);
			output.writeInt(this.newMessageAutoDeleteTime);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatEventMessageAutoDeleteTimeChanged chatEventMessageAutoDeleteTimeChanged = (ChatEventMessageAutoDeleteTimeChanged) o;
			if (this.oldMessageAutoDeleteTime != chatEventMessageAutoDeleteTimeChanged.oldMessageAutoDeleteTime) {
				return false;
			}
			if (this.newMessageAutoDeleteTime != chatEventMessageAutoDeleteTimeChanged.newMessageAutoDeleteTime) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.oldMessageAutoDeleteTime);
			return result;
		}
	}

	/**
	 * The chat permissions was changed.
	**/
	public static final class ChatEventPermissionsChanged extends ChatEventAction {


		/**
		 * Previous chat permissions.
		**/
		public ChatPermissions oldPermissions;

		/**
		 * New chat permissions.
		**/
		public ChatPermissions newPermissions;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1311557720;

		/**
		 * The chat permissions was changed.
		**/
		public ChatEventPermissionsChanged() {}

		/**
		 * The chat permissions was changed.
		 *
		 * @param oldPermissions Previous chat permissions.
		 * @param newPermissions New chat permissions.
		**/
		public ChatEventPermissionsChanged(ChatPermissions oldPermissions,
				ChatPermissions newPermissions) {
			this.oldPermissions = oldPermissions;
			this.newPermissions = newPermissions;
		}

		/**
		 * The chat permissions was changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatEventPermissionsChanged(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (ChatPermissions.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.oldPermissions = new ChatPermissions(input);
			}
			if (input.readBoolean()) {
				if (ChatPermissions.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.newPermissions = new ChatPermissions(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatEventPermissionsChanged.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatEventPermissionsChanged.CONSTRUCTOR);
			if (this.oldPermissions == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.oldPermissions.serialize(output);
			}
			if (this.newPermissions == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.newPermissions.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatEventPermissionsChanged chatEventPermissionsChanged = (ChatEventPermissionsChanged) o;
			if (!Objects.equals(this.oldPermissions, chatEventPermissionsChanged.oldPermissions)) {
				return false;
			}
			if (!Objects.equals(this.newPermissions, chatEventPermissionsChanged.newPermissions)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.oldPermissions == null ? 0 : this.oldPermissions.hashCode();
			result = result * 31 + (this.newPermissions == null ? 0 : this.newPermissions.hashCode());
			return result;
		}
	}

	/**
	 * The chat photo was changed.
	**/
	public static final class ChatEventPhotoChanged extends ChatEventAction {


		/**
		 * Previous chat photo value; may be null.
		**/
		public ChatPhoto oldPhoto;

		/**
		 * New chat photo value; may be null.
		**/
		public ChatPhoto newPhoto;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -811572541;

		/**
		 * The chat photo was changed.
		**/
		public ChatEventPhotoChanged() {}

		/**
		 * The chat photo was changed.
		 *
		 * @param oldPhoto Previous chat photo value; may be null.
		 * @param newPhoto New chat photo value; may be null.
		**/
		public ChatEventPhotoChanged(ChatPhoto oldPhoto, ChatPhoto newPhoto) {
			this.oldPhoto = oldPhoto;
			this.newPhoto = newPhoto;
		}

		/**
		 * The chat photo was changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatEventPhotoChanged(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (ChatPhoto.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.oldPhoto = new ChatPhoto(input);
			}
			if (input.readBoolean()) {
				if (ChatPhoto.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.newPhoto = new ChatPhoto(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatEventPhotoChanged.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatEventPhotoChanged.CONSTRUCTOR);
			if (this.oldPhoto == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.oldPhoto.serialize(output);
			}
			if (this.newPhoto == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.newPhoto.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatEventPhotoChanged chatEventPhotoChanged = (ChatEventPhotoChanged) o;
			if (!Objects.equals(this.oldPhoto, chatEventPhotoChanged.oldPhoto)) {
				return false;
			}
			if (!Objects.equals(this.newPhoto, chatEventPhotoChanged.newPhoto)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.oldPhoto == null ? 0 : this.oldPhoto.hashCode();
			result = result * 31 + (this.newPhoto == null ? 0 : this.newPhoto.hashCode());
			return result;
		}
	}

	/**
	 * The slowModeDelay setting of a supergroup was changed.
	**/
	public static final class ChatEventSlowModeDelayChanged extends ChatEventAction {


		/**
		 * Previous value of slowModeDelay, in seconds.
		**/
		public int oldSlowModeDelay;

		/**
		 * New value of slowModeDelay, in seconds.
		**/
		public int newSlowModeDelay;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1653195765;

		/**
		 * The slowModeDelay setting of a supergroup was changed.
		**/
		public ChatEventSlowModeDelayChanged() {}

		/**
		 * The slowModeDelay setting of a supergroup was changed.
		 *
		 * @param oldSlowModeDelay Previous value of slowModeDelay, in seconds.
		 * @param newSlowModeDelay New value of slowModeDelay, in seconds.
		**/
		public ChatEventSlowModeDelayChanged(int oldSlowModeDelay, int newSlowModeDelay) {
			this.oldSlowModeDelay = oldSlowModeDelay;
			this.newSlowModeDelay = newSlowModeDelay;
		}

		/**
		 * The slowModeDelay setting of a supergroup was changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatEventSlowModeDelayChanged(DataInput input) throws IOException {
			this.oldSlowModeDelay = input.readInt();
			this.newSlowModeDelay = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatEventSlowModeDelayChanged.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatEventSlowModeDelayChanged.CONSTRUCTOR);
			output.writeInt(this.oldSlowModeDelay);
			output.writeInt(this.newSlowModeDelay);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatEventSlowModeDelayChanged chatEventSlowModeDelayChanged = (ChatEventSlowModeDelayChanged) o;
			if (this.oldSlowModeDelay != chatEventSlowModeDelayChanged.oldSlowModeDelay) {
				return false;
			}
			if (this.newSlowModeDelay != chatEventSlowModeDelayChanged.newSlowModeDelay) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.oldSlowModeDelay);
			return result;
		}
	}

	/**
	 * The supergroup sticker set was changed.
	**/
	public static final class ChatEventStickerSetChanged extends ChatEventAction {


		/**
		 * Previous identifier of the chat sticker set; 0 if none.
		**/
		public long oldStickerSetId;

		/**
		 * New identifier of the chat sticker set; 0 if none.
		**/
		public long newStickerSetId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1243130481;

		/**
		 * The supergroup sticker set was changed.
		**/
		public ChatEventStickerSetChanged() {}

		/**
		 * The supergroup sticker set was changed.
		 *
		 * @param oldStickerSetId Previous identifier of the chat sticker set; 0 if none.
		 * @param newStickerSetId New identifier of the chat sticker set; 0 if none.
		**/
		public ChatEventStickerSetChanged(long oldStickerSetId, long newStickerSetId) {
			this.oldStickerSetId = oldStickerSetId;
			this.newStickerSetId = newStickerSetId;
		}

		/**
		 * The supergroup sticker set was changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatEventStickerSetChanged(DataInput input) throws IOException {
			this.oldStickerSetId = input.readLong();
			this.newStickerSetId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatEventStickerSetChanged.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatEventStickerSetChanged.CONSTRUCTOR);
			output.writeLong(this.oldStickerSetId);
			output.writeLong(this.newStickerSetId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatEventStickerSetChanged chatEventStickerSetChanged = (ChatEventStickerSetChanged) o;
			if (this.oldStickerSetId != chatEventStickerSetChanged.oldStickerSetId) {
				return false;
			}
			if (this.newStickerSetId != chatEventStickerSetChanged.newStickerSetId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.oldStickerSetId);
			return result;
		}
	}

	/**
	 * The chat title was changed.
	**/
	public static final class ChatEventTitleChanged extends ChatEventAction {


		/**
		 * Previous chat title.
		**/
		public String oldTitle;

		/**
		 * New chat title.
		**/
		public String newTitle;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1134103250;

		/**
		 * The chat title was changed.
		**/
		public ChatEventTitleChanged() {}

		/**
		 * The chat title was changed.
		 *
		 * @param oldTitle Previous chat title.
		 * @param newTitle New chat title.
		**/
		public ChatEventTitleChanged(String oldTitle, String newTitle) {
			this.oldTitle = oldTitle;
			this.newTitle = newTitle;
		}

		/**
		 * The chat title was changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatEventTitleChanged(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] oldTitleTmp = new byte[input.readInt()];
				input.readFully(oldTitleTmp);
				this.oldTitle = new String(oldTitleTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] newTitleTmp = new byte[input.readInt()];
				input.readFully(newTitleTmp);
				this.newTitle = new String(newTitleTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatEventTitleChanged.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatEventTitleChanged.CONSTRUCTOR);
			if (this.oldTitle == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] oldTitleTmp = this.oldTitle.getBytes(StandardCharsets.UTF_8);
				output.writeInt(oldTitleTmp.length);
				output.write(oldTitleTmp);
			}
			if (this.newTitle == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] newTitleTmp = this.newTitle.getBytes(StandardCharsets.UTF_8);
				output.writeInt(newTitleTmp.length);
				output.write(newTitleTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatEventTitleChanged chatEventTitleChanged = (ChatEventTitleChanged) o;
			if (this.oldTitle != chatEventTitleChanged.oldTitle) {
				return false;
			}
			if (this.newTitle != chatEventTitleChanged.newTitle) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.oldTitle == null ? 0 : this.oldTitle.hashCode();
			result = result * 31 + (this.newTitle == null ? 0 : this.newTitle.hashCode());
			return result;
		}
	}

	/**
	 * The chat editable username was changed.
	**/
	public static final class ChatEventUsernameChanged extends ChatEventAction {


		/**
		 * Previous chat username.
		**/
		public String oldUsername;

		/**
		 * New chat username.
		**/
		public String newUsername;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1728558443;

		/**
		 * The chat editable username was changed.
		**/
		public ChatEventUsernameChanged() {}

		/**
		 * The chat editable username was changed.
		 *
		 * @param oldUsername Previous chat username.
		 * @param newUsername New chat username.
		**/
		public ChatEventUsernameChanged(String oldUsername, String newUsername) {
			this.oldUsername = oldUsername;
			this.newUsername = newUsername;
		}

		/**
		 * The chat editable username was changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatEventUsernameChanged(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] oldUsernameTmp = new byte[input.readInt()];
				input.readFully(oldUsernameTmp);
				this.oldUsername = new String(oldUsernameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] newUsernameTmp = new byte[input.readInt()];
				input.readFully(newUsernameTmp);
				this.newUsername = new String(newUsernameTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatEventUsernameChanged.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatEventUsernameChanged.CONSTRUCTOR);
			if (this.oldUsername == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] oldUsernameTmp = this.oldUsername.getBytes(StandardCharsets.UTF_8);
				output.writeInt(oldUsernameTmp.length);
				output.write(oldUsernameTmp);
			}
			if (this.newUsername == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] newUsernameTmp = this.newUsername.getBytes(StandardCharsets.UTF_8);
				output.writeInt(newUsernameTmp.length);
				output.write(newUsernameTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatEventUsernameChanged chatEventUsernameChanged = (ChatEventUsernameChanged) o;
			if (this.oldUsername != chatEventUsernameChanged.oldUsername) {
				return false;
			}
			if (this.newUsername != chatEventUsernameChanged.newUsername) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.oldUsername == null ? 0 : this.oldUsername.hashCode();
			result = result * 31 + (this.newUsername == null ? 0 : this.newUsername.hashCode());
			return result;
		}
	}

	/**
	 * The chat active usernames were changed.
	**/
	public static final class ChatEventActiveUsernamesChanged extends ChatEventAction {


		/**
		 * Previous list of active usernames.
		**/
		public String[] oldUsernames;

		/**
		 * New list of active usernames.
		**/
		public String[] newUsernames;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1508790810;

		/**
		 * The chat active usernames were changed.
		**/
		public ChatEventActiveUsernamesChanged() {}

		/**
		 * The chat active usernames were changed.
		 *
		 * @param oldUsernames Previous list of active usernames.
		 * @param newUsernames New list of active usernames.
		**/
		public ChatEventActiveUsernamesChanged(String[] oldUsernames, String[] newUsernames) {
			this.oldUsernames = oldUsernames;
			this.newUsernames = newUsernames;
		}

		/**
		 * The chat active usernames were changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatEventActiveUsernamesChanged(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.oldUsernames = new String[input.readInt()];
				for (int i = 0; i < this.oldUsernames.length; i++) {
					byte[] oldUsernamesTmp = new byte[input.readInt()];
					input.readFully(oldUsernamesTmp);
					this.oldUsernames[i] = new String(oldUsernamesTmp, StandardCharsets.UTF_8);
				}
			}
			if (input.readBoolean()) {
				this.newUsernames = new String[input.readInt()];
				for (int i = 0; i < this.newUsernames.length; i++) {
					byte[] newUsernamesTmp = new byte[input.readInt()];
					input.readFully(newUsernamesTmp);
					this.newUsernames[i] = new String(newUsernamesTmp, StandardCharsets.UTF_8);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatEventActiveUsernamesChanged.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatEventActiveUsernamesChanged.CONSTRUCTOR);
			if (this.oldUsernames == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.oldUsernames.length);
				for (int i = 0; i < this.oldUsernames.length; i++) {
					byte[] oldUsernamesTmp = this.oldUsernames[i].getBytes(StandardCharsets.UTF_8);
					output.writeInt(oldUsernamesTmp.length);
					output.write(oldUsernamesTmp);
				}
			}
			if (this.newUsernames == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.newUsernames.length);
				for (int i = 0; i < this.newUsernames.length; i++) {
					byte[] newUsernamesTmp = this.newUsernames[i].getBytes(StandardCharsets.UTF_8);
					output.writeInt(newUsernamesTmp.length);
					output.write(newUsernamesTmp);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatEventActiveUsernamesChanged chatEventActiveUsernamesChanged = (ChatEventActiveUsernamesChanged) o;
			if (!Arrays.equals(this.oldUsernames, chatEventActiveUsernamesChanged.oldUsernames)) {
				return false;
			}
			if (!Arrays.equals(this.newUsernames, chatEventActiveUsernamesChanged.newUsernames)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Arrays.hashCode(this.oldUsernames);
			result = result * 31 + (Arrays.hashCode(this.newUsernames));
			return result;
		}
	}

	/**
	 * The hasProtectedContent setting of a channel was toggled.
	**/
	public static final class ChatEventHasProtectedContentToggled extends ChatEventAction {


		/**
		 * New value of hasProtectedContent.
		**/
		public boolean hasProtectedContent;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -184270335;

		/**
		 * The hasProtectedContent setting of a channel was toggled.
		**/
		public ChatEventHasProtectedContentToggled() {}

		/**
		 * The hasProtectedContent setting of a channel was toggled.
		 *
		 * @param hasProtectedContent New value of hasProtectedContent.
		**/
		public ChatEventHasProtectedContentToggled(boolean hasProtectedContent) {
			this.hasProtectedContent = hasProtectedContent;
		}

		/**
		 * The hasProtectedContent setting of a channel was toggled.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatEventHasProtectedContentToggled(DataInput input) throws IOException {
			this.hasProtectedContent = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatEventHasProtectedContentToggled.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatEventHasProtectedContentToggled.CONSTRUCTOR);
			output.writeBoolean(this.hasProtectedContent);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatEventHasProtectedContentToggled chatEventHasProtectedContentToggled = (ChatEventHasProtectedContentToggled) o;
			if (this.hasProtectedContent != chatEventHasProtectedContentToggled.hasProtectedContent) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Boolean.hashCode(this.hasProtectedContent);
		}
	}

	/**
	 * The canInviteUsers permission of a supergroup chat was toggled.
	**/
	public static final class ChatEventInvitesToggled extends ChatEventAction {


		/**
		 * New value of canInviteUsers permission.
		**/
		public boolean canInviteUsers;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -62548373;

		/**
		 * The canInviteUsers permission of a supergroup chat was toggled.
		**/
		public ChatEventInvitesToggled() {}

		/**
		 * The canInviteUsers permission of a supergroup chat was toggled.
		 *
		 * @param canInviteUsers New value of canInviteUsers permission.
		**/
		public ChatEventInvitesToggled(boolean canInviteUsers) {
			this.canInviteUsers = canInviteUsers;
		}

		/**
		 * The canInviteUsers permission of a supergroup chat was toggled.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatEventInvitesToggled(DataInput input) throws IOException {
			this.canInviteUsers = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatEventInvitesToggled.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatEventInvitesToggled.CONSTRUCTOR);
			output.writeBoolean(this.canInviteUsers);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatEventInvitesToggled chatEventInvitesToggled = (ChatEventInvitesToggled) o;
			if (this.canInviteUsers != chatEventInvitesToggled.canInviteUsers) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Boolean.hashCode(this.canInviteUsers);
		}
	}

	/**
	 * The isAllHistoryAvailable setting of a supergroup was toggled.
	**/
	public static final class ChatEventIsAllHistoryAvailableToggled extends ChatEventAction {


		/**
		 * New value of isAllHistoryAvailable.
		**/
		public boolean isAllHistoryAvailable;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1599063019;

		/**
		 * The isAllHistoryAvailable setting of a supergroup was toggled.
		**/
		public ChatEventIsAllHistoryAvailableToggled() {}

		/**
		 * The isAllHistoryAvailable setting of a supergroup was toggled.
		 *
		 * @param isAllHistoryAvailable New value of isAllHistoryAvailable.
		**/
		public ChatEventIsAllHistoryAvailableToggled(boolean isAllHistoryAvailable) {
			this.isAllHistoryAvailable = isAllHistoryAvailable;
		}

		/**
		 * The isAllHistoryAvailable setting of a supergroup was toggled.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatEventIsAllHistoryAvailableToggled(DataInput input) throws IOException {
			this.isAllHistoryAvailable = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatEventIsAllHistoryAvailableToggled.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatEventIsAllHistoryAvailableToggled.CONSTRUCTOR);
			output.writeBoolean(this.isAllHistoryAvailable);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatEventIsAllHistoryAvailableToggled chatEventIsAllHistoryAvailableToggled = (ChatEventIsAllHistoryAvailableToggled) o;
			if (this.isAllHistoryAvailable != chatEventIsAllHistoryAvailableToggled.isAllHistoryAvailable) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Boolean.hashCode(this.isAllHistoryAvailable);
		}
	}

	/**
	 * The hasAggressiveAntiSpamEnabled setting of a supergroup was toggled.
	**/
	public static final class ChatEventHasAggressiveAntiSpamEnabledToggled extends ChatEventAction {


		/**
		 * New value of hasAggressiveAntiSpamEnabled.
		**/
		public boolean hasAggressiveAntiSpamEnabled;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -125348094;

		/**
		 * The hasAggressiveAntiSpamEnabled setting of a supergroup was toggled.
		**/
		public ChatEventHasAggressiveAntiSpamEnabledToggled() {}

		/**
		 * The hasAggressiveAntiSpamEnabled setting of a supergroup was toggled.
		 *
		 * @param hasAggressiveAntiSpamEnabled New value of hasAggressiveAntiSpamEnabled.
		**/
		public ChatEventHasAggressiveAntiSpamEnabledToggled(boolean hasAggressiveAntiSpamEnabled) {
			this.hasAggressiveAntiSpamEnabled = hasAggressiveAntiSpamEnabled;
		}

		/**
		 * The hasAggressiveAntiSpamEnabled setting of a supergroup was toggled.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatEventHasAggressiveAntiSpamEnabledToggled(DataInput input) throws IOException {
			this.hasAggressiveAntiSpamEnabled = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatEventHasAggressiveAntiSpamEnabledToggled.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatEventHasAggressiveAntiSpamEnabledToggled.CONSTRUCTOR);
			output.writeBoolean(this.hasAggressiveAntiSpamEnabled);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatEventHasAggressiveAntiSpamEnabledToggled chatEventHasAggressiveAntiSpamEnabledToggled = (ChatEventHasAggressiveAntiSpamEnabledToggled) o;
			if (this.hasAggressiveAntiSpamEnabled != chatEventHasAggressiveAntiSpamEnabledToggled.hasAggressiveAntiSpamEnabled) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Boolean.hashCode(this.hasAggressiveAntiSpamEnabled);
		}
	}

	/**
	 * The signMessages setting of a channel was toggled.
	**/
	public static final class ChatEventSignMessagesToggled extends ChatEventAction {


		/**
		 * New value of signMessages.
		**/
		public boolean signMessages;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1313265634;

		/**
		 * The signMessages setting of a channel was toggled.
		**/
		public ChatEventSignMessagesToggled() {}

		/**
		 * The signMessages setting of a channel was toggled.
		 *
		 * @param signMessages New value of signMessages.
		**/
		public ChatEventSignMessagesToggled(boolean signMessages) {
			this.signMessages = signMessages;
		}

		/**
		 * The signMessages setting of a channel was toggled.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatEventSignMessagesToggled(DataInput input) throws IOException {
			this.signMessages = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatEventSignMessagesToggled.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatEventSignMessagesToggled.CONSTRUCTOR);
			output.writeBoolean(this.signMessages);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatEventSignMessagesToggled chatEventSignMessagesToggled = (ChatEventSignMessagesToggled) o;
			if (this.signMessages != chatEventSignMessagesToggled.signMessages) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Boolean.hashCode(this.signMessages);
		}
	}

	/**
	 * A chat invite link was edited.
	**/
	public static final class ChatEventInviteLinkEdited extends ChatEventAction {


		/**
		 * Previous information about the invite link.
		**/
		public ChatInviteLink oldInviteLink;

		/**
		 * New information about the invite link.
		**/
		public ChatInviteLink newInviteLink;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -460190366;

		/**
		 * A chat invite link was edited.
		**/
		public ChatEventInviteLinkEdited() {}

		/**
		 * A chat invite link was edited.
		 *
		 * @param oldInviteLink Previous information about the invite link.
		 * @param newInviteLink New information about the invite link.
		**/
		public ChatEventInviteLinkEdited(ChatInviteLink oldInviteLink, ChatInviteLink newInviteLink) {
			this.oldInviteLink = oldInviteLink;
			this.newInviteLink = newInviteLink;
		}

		/**
		 * A chat invite link was edited.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatEventInviteLinkEdited(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (ChatInviteLink.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.oldInviteLink = new ChatInviteLink(input);
			}
			if (input.readBoolean()) {
				if (ChatInviteLink.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.newInviteLink = new ChatInviteLink(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatEventInviteLinkEdited.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatEventInviteLinkEdited.CONSTRUCTOR);
			if (this.oldInviteLink == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.oldInviteLink.serialize(output);
			}
			if (this.newInviteLink == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.newInviteLink.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatEventInviteLinkEdited chatEventInviteLinkEdited = (ChatEventInviteLinkEdited) o;
			if (!Objects.equals(this.oldInviteLink, chatEventInviteLinkEdited.oldInviteLink)) {
				return false;
			}
			if (!Objects.equals(this.newInviteLink, chatEventInviteLinkEdited.newInviteLink)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.oldInviteLink == null ? 0 : this.oldInviteLink.hashCode();
			result = result * 31 + (this.newInviteLink == null ? 0 : this.newInviteLink.hashCode());
			return result;
		}
	}

	/**
	 * A chat invite link was revoked.
	**/
	public static final class ChatEventInviteLinkRevoked extends ChatEventAction {


		/**
		 * The invite link.
		**/
		public ChatInviteLink inviteLink;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1579417629;

		/**
		 * A chat invite link was revoked.
		**/
		public ChatEventInviteLinkRevoked() {}

		/**
		 * A chat invite link was revoked.
		 *
		 * @param inviteLink The invite link.
		**/
		public ChatEventInviteLinkRevoked(ChatInviteLink inviteLink) {
			this.inviteLink = inviteLink;
		}

		/**
		 * A chat invite link was revoked.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatEventInviteLinkRevoked(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (ChatInviteLink.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.inviteLink = new ChatInviteLink(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatEventInviteLinkRevoked.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatEventInviteLinkRevoked.CONSTRUCTOR);
			if (this.inviteLink == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.inviteLink.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatEventInviteLinkRevoked chatEventInviteLinkRevoked = (ChatEventInviteLinkRevoked) o;
			if (!Objects.equals(this.inviteLink, chatEventInviteLinkRevoked.inviteLink)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.inviteLink == null ? 0 : this.inviteLink.hashCode();
		}
	}

	/**
	 * A revoked chat invite link was deleted.
	**/
	public static final class ChatEventInviteLinkDeleted extends ChatEventAction {


		/**
		 * The invite link.
		**/
		public ChatInviteLink inviteLink;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1394974361;

		/**
		 * A revoked chat invite link was deleted.
		**/
		public ChatEventInviteLinkDeleted() {}

		/**
		 * A revoked chat invite link was deleted.
		 *
		 * @param inviteLink The invite link.
		**/
		public ChatEventInviteLinkDeleted(ChatInviteLink inviteLink) {
			this.inviteLink = inviteLink;
		}

		/**
		 * A revoked chat invite link was deleted.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatEventInviteLinkDeleted(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (ChatInviteLink.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.inviteLink = new ChatInviteLink(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatEventInviteLinkDeleted.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatEventInviteLinkDeleted.CONSTRUCTOR);
			if (this.inviteLink == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.inviteLink.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatEventInviteLinkDeleted chatEventInviteLinkDeleted = (ChatEventInviteLinkDeleted) o;
			if (!Objects.equals(this.inviteLink, chatEventInviteLinkDeleted.inviteLink)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.inviteLink == null ? 0 : this.inviteLink.hashCode();
		}
	}

	/**
	 * A video chat was created.
	**/
	public static final class ChatEventVideoChatCreated extends ChatEventAction {


		/**
		 * Identifier of the video chat. The video chat can be received through the method getGroupCall.
		**/
		public int groupCallId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1822853755;

		/**
		 * A video chat was created.
		**/
		public ChatEventVideoChatCreated() {}

		/**
		 * A video chat was created.
		 *
		 * @param groupCallId Identifier of the video chat. The video chat can be received through the method getGroupCall.
		**/
		public ChatEventVideoChatCreated(int groupCallId) {
			this.groupCallId = groupCallId;
		}

		/**
		 * A video chat was created.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatEventVideoChatCreated(DataInput input) throws IOException {
			this.groupCallId = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatEventVideoChatCreated.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatEventVideoChatCreated.CONSTRUCTOR);
			output.writeInt(this.groupCallId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatEventVideoChatCreated chatEventVideoChatCreated = (ChatEventVideoChatCreated) o;
			if (this.groupCallId != chatEventVideoChatCreated.groupCallId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.groupCallId);
		}
	}

	/**
	 * A video chat was ended.
	**/
	public static final class ChatEventVideoChatEnded extends ChatEventAction {


		/**
		 * Identifier of the video chat. The video chat can be received through the method getGroupCall.
		**/
		public int groupCallId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1630039112;

		/**
		 * A video chat was ended.
		**/
		public ChatEventVideoChatEnded() {}

		/**
		 * A video chat was ended.
		 *
		 * @param groupCallId Identifier of the video chat. The video chat can be received through the method getGroupCall.
		**/
		public ChatEventVideoChatEnded(int groupCallId) {
			this.groupCallId = groupCallId;
		}

		/**
		 * A video chat was ended.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatEventVideoChatEnded(DataInput input) throws IOException {
			this.groupCallId = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatEventVideoChatEnded.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatEventVideoChatEnded.CONSTRUCTOR);
			output.writeInt(this.groupCallId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatEventVideoChatEnded chatEventVideoChatEnded = (ChatEventVideoChatEnded) o;
			if (this.groupCallId != chatEventVideoChatEnded.groupCallId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.groupCallId);
		}
	}

	/**
	 * The muteNewParticipants setting of a video chat was toggled.
	**/
	public static final class ChatEventVideoChatMuteNewParticipantsToggled extends ChatEventAction {


		/**
		 * New value of the muteNewParticipants setting.
		**/
		public boolean muteNewParticipants;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -126547970;

		/**
		 * The muteNewParticipants setting of a video chat was toggled.
		**/
		public ChatEventVideoChatMuteNewParticipantsToggled() {}

		/**
		 * The muteNewParticipants setting of a video chat was toggled.
		 *
		 * @param muteNewParticipants New value of the muteNewParticipants setting.
		**/
		public ChatEventVideoChatMuteNewParticipantsToggled(boolean muteNewParticipants) {
			this.muteNewParticipants = muteNewParticipants;
		}

		/**
		 * The muteNewParticipants setting of a video chat was toggled.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatEventVideoChatMuteNewParticipantsToggled(DataInput input) throws IOException {
			this.muteNewParticipants = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatEventVideoChatMuteNewParticipantsToggled.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatEventVideoChatMuteNewParticipantsToggled.CONSTRUCTOR);
			output.writeBoolean(this.muteNewParticipants);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatEventVideoChatMuteNewParticipantsToggled chatEventVideoChatMuteNewParticipantsToggled = (ChatEventVideoChatMuteNewParticipantsToggled) o;
			if (this.muteNewParticipants != chatEventVideoChatMuteNewParticipantsToggled.muteNewParticipants) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Boolean.hashCode(this.muteNewParticipants);
		}
	}

	/**
	 * A video chat participant was muted or unmuted.
	**/
	public static final class ChatEventVideoChatParticipantIsMutedToggled extends ChatEventAction {


		/**
		 * Identifier of the affected group call participant.
		**/
		public MessageSender participantId;

		/**
		 * New value of isMuted.
		**/
		public boolean isMuted;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 521165047;

		/**
		 * A video chat participant was muted or unmuted.
		**/
		public ChatEventVideoChatParticipantIsMutedToggled() {}

		/**
		 * A video chat participant was muted or unmuted.
		 *
		 * @param participantId Identifier of the affected group call participant.
		 * @param isMuted New value of isMuted.
		**/
		public ChatEventVideoChatParticipantIsMutedToggled(MessageSender participantId, boolean isMuted) {
			this.participantId = participantId;
			this.isMuted = isMuted;
		}

		/**
		 * A video chat participant was muted or unmuted.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatEventVideoChatParticipantIsMutedToggled(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case MessageSenderUser.CONSTRUCTOR: this.participantId = new MessageSenderUser(input); break;
					case MessageSenderChat.CONSTRUCTOR: this.participantId = new MessageSenderChat(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.isMuted = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatEventVideoChatParticipantIsMutedToggled.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatEventVideoChatParticipantIsMutedToggled.CONSTRUCTOR);
			if (this.participantId == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.participantId.serialize(output);
			}
			output.writeBoolean(this.isMuted);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatEventVideoChatParticipantIsMutedToggled chatEventVideoChatParticipantIsMutedToggled = (ChatEventVideoChatParticipantIsMutedToggled) o;
			if (!Objects.equals(this.participantId, chatEventVideoChatParticipantIsMutedToggled.participantId)) {
				return false;
			}
			if (this.isMuted != chatEventVideoChatParticipantIsMutedToggled.isMuted) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isMuted);
			result = result * 31 + (this.participantId == null ? 0 : this.participantId.hashCode());
			return result;
		}
	}

	/**
	 * A video chat participant volume level was changed.
	**/
	public static final class ChatEventVideoChatParticipantVolumeLevelChanged extends ChatEventAction {


		/**
		 * Identifier of the affected group call participant.
		**/
		public MessageSender participantId;

		/**
		 * New value of volumeLevel; 1-20000 in hundreds of percents.
		**/
		public int volumeLevel;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1131385534;

		/**
		 * A video chat participant volume level was changed.
		**/
		public ChatEventVideoChatParticipantVolumeLevelChanged() {}

		/**
		 * A video chat participant volume level was changed.
		 *
		 * @param participantId Identifier of the affected group call participant.
		 * @param volumeLevel New value of volumeLevel; 1-20000 in hundreds of percents.
		**/
		public ChatEventVideoChatParticipantVolumeLevelChanged(MessageSender participantId, int volumeLevel) {
			this.participantId = participantId;
			this.volumeLevel = volumeLevel;
		}

		/**
		 * A video chat participant volume level was changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatEventVideoChatParticipantVolumeLevelChanged(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case MessageSenderUser.CONSTRUCTOR: this.participantId = new MessageSenderUser(input); break;
					case MessageSenderChat.CONSTRUCTOR: this.participantId = new MessageSenderChat(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.volumeLevel = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatEventVideoChatParticipantVolumeLevelChanged.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatEventVideoChatParticipantVolumeLevelChanged.CONSTRUCTOR);
			if (this.participantId == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.participantId.serialize(output);
			}
			output.writeInt(this.volumeLevel);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatEventVideoChatParticipantVolumeLevelChanged chatEventVideoChatParticipantVolumeLevelChanged = (ChatEventVideoChatParticipantVolumeLevelChanged) o;
			if (!Objects.equals(this.participantId, chatEventVideoChatParticipantVolumeLevelChanged.participantId)) {
				return false;
			}
			if (this.volumeLevel != chatEventVideoChatParticipantVolumeLevelChanged.volumeLevel) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.volumeLevel);
			result = result * 31 + (this.participantId == null ? 0 : this.participantId.hashCode());
			return result;
		}
	}

	/**
	 * The isForum setting of a channel was toggled.
	**/
	public static final class ChatEventIsForumToggled extends ChatEventAction {


		/**
		 * New value of isForum.
		**/
		public boolean isForum;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1516491033;

		/**
		 * The isForum setting of a channel was toggled.
		**/
		public ChatEventIsForumToggled() {}

		/**
		 * The isForum setting of a channel was toggled.
		 *
		 * @param isForum New value of isForum.
		**/
		public ChatEventIsForumToggled(boolean isForum) {
			this.isForum = isForum;
		}

		/**
		 * The isForum setting of a channel was toggled.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatEventIsForumToggled(DataInput input) throws IOException {
			this.isForum = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatEventIsForumToggled.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatEventIsForumToggled.CONSTRUCTOR);
			output.writeBoolean(this.isForum);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatEventIsForumToggled chatEventIsForumToggled = (ChatEventIsForumToggled) o;
			if (this.isForum != chatEventIsForumToggled.isForum) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Boolean.hashCode(this.isForum);
		}
	}

	/**
	 * A new forum topic was created.
	**/
	public static final class ChatEventForumTopicCreated extends ChatEventAction {


		/**
		 * Information about the topic.
		**/
		public ForumTopicInfo topicInfo;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2005269314;

		/**
		 * A new forum topic was created.
		**/
		public ChatEventForumTopicCreated() {}

		/**
		 * A new forum topic was created.
		 *
		 * @param topicInfo Information about the topic.
		**/
		public ChatEventForumTopicCreated(ForumTopicInfo topicInfo) {
			this.topicInfo = topicInfo;
		}

		/**
		 * A new forum topic was created.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatEventForumTopicCreated(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (ForumTopicInfo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.topicInfo = new ForumTopicInfo(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatEventForumTopicCreated.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatEventForumTopicCreated.CONSTRUCTOR);
			if (this.topicInfo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.topicInfo.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatEventForumTopicCreated chatEventForumTopicCreated = (ChatEventForumTopicCreated) o;
			if (!Objects.equals(this.topicInfo, chatEventForumTopicCreated.topicInfo)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.topicInfo == null ? 0 : this.topicInfo.hashCode();
		}
	}

	/**
	 * A forum topic was edited.
	**/
	public static final class ChatEventForumTopicEdited extends ChatEventAction {


		/**
		 * Old information about the topic.
		**/
		public ForumTopicInfo oldTopicInfo;

		/**
		 * New information about the topic.
		**/
		public ForumTopicInfo newTopicInfo;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1624910860;

		/**
		 * A forum topic was edited.
		**/
		public ChatEventForumTopicEdited() {}

		/**
		 * A forum topic was edited.
		 *
		 * @param oldTopicInfo Old information about the topic.
		 * @param newTopicInfo New information about the topic.
		**/
		public ChatEventForumTopicEdited(ForumTopicInfo oldTopicInfo, ForumTopicInfo newTopicInfo) {
			this.oldTopicInfo = oldTopicInfo;
			this.newTopicInfo = newTopicInfo;
		}

		/**
		 * A forum topic was edited.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatEventForumTopicEdited(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (ForumTopicInfo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.oldTopicInfo = new ForumTopicInfo(input);
			}
			if (input.readBoolean()) {
				if (ForumTopicInfo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.newTopicInfo = new ForumTopicInfo(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatEventForumTopicEdited.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatEventForumTopicEdited.CONSTRUCTOR);
			if (this.oldTopicInfo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.oldTopicInfo.serialize(output);
			}
			if (this.newTopicInfo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.newTopicInfo.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatEventForumTopicEdited chatEventForumTopicEdited = (ChatEventForumTopicEdited) o;
			if (!Objects.equals(this.oldTopicInfo, chatEventForumTopicEdited.oldTopicInfo)) {
				return false;
			}
			if (!Objects.equals(this.newTopicInfo, chatEventForumTopicEdited.newTopicInfo)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.oldTopicInfo == null ? 0 : this.oldTopicInfo.hashCode();
			result = result * 31 + (this.newTopicInfo == null ? 0 : this.newTopicInfo.hashCode());
			return result;
		}
	}

	/**
	 * A forum topic was closed or reopened.
	**/
	public static final class ChatEventForumTopicToggleIsClosed extends ChatEventAction {


		/**
		 * New information about the topic.
		**/
		public ForumTopicInfo topicInfo;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -962704070;

		/**
		 * A forum topic was closed or reopened.
		**/
		public ChatEventForumTopicToggleIsClosed() {}

		/**
		 * A forum topic was closed or reopened.
		 *
		 * @param topicInfo New information about the topic.
		**/
		public ChatEventForumTopicToggleIsClosed(ForumTopicInfo topicInfo) {
			this.topicInfo = topicInfo;
		}

		/**
		 * A forum topic was closed or reopened.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatEventForumTopicToggleIsClosed(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (ForumTopicInfo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.topicInfo = new ForumTopicInfo(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatEventForumTopicToggleIsClosed.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatEventForumTopicToggleIsClosed.CONSTRUCTOR);
			if (this.topicInfo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.topicInfo.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatEventForumTopicToggleIsClosed chatEventForumTopicToggleIsClosed = (ChatEventForumTopicToggleIsClosed) o;
			if (!Objects.equals(this.topicInfo, chatEventForumTopicToggleIsClosed.topicInfo)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.topicInfo == null ? 0 : this.topicInfo.hashCode();
		}
	}

	/**
	 * The General forum topic was hidden or unhidden.
	**/
	public static final class ChatEventForumTopicToggleIsHidden extends ChatEventAction {


		/**
		 * New information about the topic.
		**/
		public ForumTopicInfo topicInfo;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1609175250;

		/**
		 * The General forum topic was hidden or unhidden.
		**/
		public ChatEventForumTopicToggleIsHidden() {}

		/**
		 * The General forum topic was hidden or unhidden.
		 *
		 * @param topicInfo New information about the topic.
		**/
		public ChatEventForumTopicToggleIsHidden(ForumTopicInfo topicInfo) {
			this.topicInfo = topicInfo;
		}

		/**
		 * The General forum topic was hidden or unhidden.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatEventForumTopicToggleIsHidden(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (ForumTopicInfo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.topicInfo = new ForumTopicInfo(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatEventForumTopicToggleIsHidden.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatEventForumTopicToggleIsHidden.CONSTRUCTOR);
			if (this.topicInfo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.topicInfo.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatEventForumTopicToggleIsHidden chatEventForumTopicToggleIsHidden = (ChatEventForumTopicToggleIsHidden) o;
			if (!Objects.equals(this.topicInfo, chatEventForumTopicToggleIsHidden.topicInfo)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.topicInfo == null ? 0 : this.topicInfo.hashCode();
		}
	}

	/**
	 * A forum topic was deleted.
	**/
	public static final class ChatEventForumTopicDeleted extends ChatEventAction {


		/**
		 * Information about the topic.
		**/
		public ForumTopicInfo topicInfo;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1332795123;

		/**
		 * A forum topic was deleted.
		**/
		public ChatEventForumTopicDeleted() {}

		/**
		 * A forum topic was deleted.
		 *
		 * @param topicInfo Information about the topic.
		**/
		public ChatEventForumTopicDeleted(ForumTopicInfo topicInfo) {
			this.topicInfo = topicInfo;
		}

		/**
		 * A forum topic was deleted.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatEventForumTopicDeleted(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (ForumTopicInfo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.topicInfo = new ForumTopicInfo(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatEventForumTopicDeleted.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatEventForumTopicDeleted.CONSTRUCTOR);
			if (this.topicInfo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.topicInfo.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatEventForumTopicDeleted chatEventForumTopicDeleted = (ChatEventForumTopicDeleted) o;
			if (!Objects.equals(this.topicInfo, chatEventForumTopicDeleted.topicInfo)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.topicInfo == null ? 0 : this.topicInfo.hashCode();
		}
	}

	/**
	 * A pinned forum topic was changed.
	**/
	public static final class ChatEventForumTopicPinned extends ChatEventAction {


		/**
		 * Information about the old pinned topic; may be null.
		**/
		public ForumTopicInfo oldTopicInfo;

		/**
		 * Information about the new pinned topic; may be null.
		**/
		public ForumTopicInfo newTopicInfo;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2143626222;

		/**
		 * A pinned forum topic was changed.
		**/
		public ChatEventForumTopicPinned() {}

		/**
		 * A pinned forum topic was changed.
		 *
		 * @param oldTopicInfo Information about the old pinned topic; may be null.
		 * @param newTopicInfo Information about the new pinned topic; may be null.
		**/
		public ChatEventForumTopicPinned(ForumTopicInfo oldTopicInfo, ForumTopicInfo newTopicInfo) {
			this.oldTopicInfo = oldTopicInfo;
			this.newTopicInfo = newTopicInfo;
		}

		/**
		 * A pinned forum topic was changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatEventForumTopicPinned(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (ForumTopicInfo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.oldTopicInfo = new ForumTopicInfo(input);
			}
			if (input.readBoolean()) {
				if (ForumTopicInfo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.newTopicInfo = new ForumTopicInfo(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatEventForumTopicPinned.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatEventForumTopicPinned.CONSTRUCTOR);
			if (this.oldTopicInfo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.oldTopicInfo.serialize(output);
			}
			if (this.newTopicInfo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.newTopicInfo.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatEventForumTopicPinned chatEventForumTopicPinned = (ChatEventForumTopicPinned) o;
			if (!Objects.equals(this.oldTopicInfo, chatEventForumTopicPinned.oldTopicInfo)) {
				return false;
			}
			if (!Objects.equals(this.newTopicInfo, chatEventForumTopicPinned.newTopicInfo)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.oldTopicInfo == null ? 0 : this.oldTopicInfo.hashCode();
			result = result * 31 + (this.newTopicInfo == null ? 0 : this.newTopicInfo.hashCode());
			return result;
		}
	}

	/**
	 * Represents a set of filters used to obtain a chat event log.
	**/
	public static final class ChatEventLogFilters extends Object {


		/**
		 * True, if message edits need to be returned.
		**/
		public boolean messageEdits;

		/**
		 * True, if message deletions need to be returned.
		**/
		public boolean messageDeletions;

		/**
		 * True, if pin/unpin events need to be returned.
		**/
		public boolean messagePins;

		/**
		 * True, if members joining events need to be returned.
		**/
		public boolean memberJoins;

		/**
		 * True, if members leaving events need to be returned.
		**/
		public boolean memberLeaves;

		/**
		 * True, if invited member events need to be returned.
		**/
		public boolean memberInvites;

		/**
		 * True, if member promotion/demotion events need to be returned.
		**/
		public boolean memberPromotions;

		/**
		 * True, if member restricted/unrestricted/banned/unbanned events need to be returned.
		**/
		public boolean memberRestrictions;

		/**
		 * True, if changes in chat information need to be returned.
		**/
		public boolean infoChanges;

		/**
		 * True, if changes in chat settings need to be returned.
		**/
		public boolean settingChanges;

		/**
		 * True, if changes to invite links need to be returned.
		**/
		public boolean inviteLinkChanges;

		/**
		 * True, if video chat actions need to be returned.
		**/
		public boolean videoChatChanges;

		/**
		 * True, if forum-related actions need to be returned.
		**/
		public boolean forumChanges;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1648261677;

		/**
		 * Represents a set of filters used to obtain a chat event log.
		**/
		public ChatEventLogFilters() {}

		/**
		 * Represents a set of filters used to obtain a chat event log.
		 *
		 * @param messageEdits True, if message edits need to be returned.
		 * @param messageDeletions True, if message deletions need to be returned.
		 * @param messagePins True, if pin/unpin events need to be returned.
		 * @param memberJoins True, if members joining events need to be returned.
		 * @param memberLeaves True, if members leaving events need to be returned.
		 * @param memberInvites True, if invited member events need to be returned.
		 * @param memberPromotions True, if member promotion/demotion events need to be returned.
		 * @param memberRestrictions True, if member restricted/unrestricted/banned/unbanned events need to be returned.
		 * @param infoChanges True, if changes in chat information need to be returned.
		 * @param settingChanges True, if changes in chat settings need to be returned.
		 * @param inviteLinkChanges True, if changes to invite links need to be returned.
		 * @param videoChatChanges True, if video chat actions need to be returned.
		 * @param forumChanges True, if forum-related actions need to be returned.
		**/
		public ChatEventLogFilters(boolean messageEdits,
				boolean messageDeletions,
				boolean messagePins,
				boolean memberJoins,
				boolean memberLeaves,
				boolean memberInvites,
				boolean memberPromotions,
				boolean memberRestrictions,
				boolean infoChanges,
				boolean settingChanges,
				boolean inviteLinkChanges,
				boolean videoChatChanges,
				boolean forumChanges) {
			this.messageEdits = messageEdits;
			this.messageDeletions = messageDeletions;
			this.messagePins = messagePins;
			this.memberJoins = memberJoins;
			this.memberLeaves = memberLeaves;
			this.memberInvites = memberInvites;
			this.memberPromotions = memberPromotions;
			this.memberRestrictions = memberRestrictions;
			this.infoChanges = infoChanges;
			this.settingChanges = settingChanges;
			this.inviteLinkChanges = inviteLinkChanges;
			this.videoChatChanges = videoChatChanges;
			this.forumChanges = forumChanges;
		}

		/**
		 * Represents a set of filters used to obtain a chat event log.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatEventLogFilters(DataInput input) throws IOException {
			this.messageEdits = input.readBoolean();
			this.messageDeletions = input.readBoolean();
			this.messagePins = input.readBoolean();
			this.memberJoins = input.readBoolean();
			this.memberLeaves = input.readBoolean();
			this.memberInvites = input.readBoolean();
			this.memberPromotions = input.readBoolean();
			this.memberRestrictions = input.readBoolean();
			this.infoChanges = input.readBoolean();
			this.settingChanges = input.readBoolean();
			this.inviteLinkChanges = input.readBoolean();
			this.videoChatChanges = input.readBoolean();
			this.forumChanges = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatEventLogFilters.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatEventLogFilters.CONSTRUCTOR);
			output.writeBoolean(this.messageEdits);
			output.writeBoolean(this.messageDeletions);
			output.writeBoolean(this.messagePins);
			output.writeBoolean(this.memberJoins);
			output.writeBoolean(this.memberLeaves);
			output.writeBoolean(this.memberInvites);
			output.writeBoolean(this.memberPromotions);
			output.writeBoolean(this.memberRestrictions);
			output.writeBoolean(this.infoChanges);
			output.writeBoolean(this.settingChanges);
			output.writeBoolean(this.inviteLinkChanges);
			output.writeBoolean(this.videoChatChanges);
			output.writeBoolean(this.forumChanges);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatEventLogFilters chatEventLogFilters = (ChatEventLogFilters) o;
			if (this.messageEdits != chatEventLogFilters.messageEdits) {
				return false;
			}
			if (this.messageDeletions != chatEventLogFilters.messageDeletions) {
				return false;
			}
			if (this.messagePins != chatEventLogFilters.messagePins) {
				return false;
			}
			if (this.memberJoins != chatEventLogFilters.memberJoins) {
				return false;
			}
			if (this.memberLeaves != chatEventLogFilters.memberLeaves) {
				return false;
			}
			if (this.memberInvites != chatEventLogFilters.memberInvites) {
				return false;
			}
			if (this.memberPromotions != chatEventLogFilters.memberPromotions) {
				return false;
			}
			if (this.memberRestrictions != chatEventLogFilters.memberRestrictions) {
				return false;
			}
			if (this.infoChanges != chatEventLogFilters.infoChanges) {
				return false;
			}
			if (this.settingChanges != chatEventLogFilters.settingChanges) {
				return false;
			}
			if (this.inviteLinkChanges != chatEventLogFilters.inviteLinkChanges) {
				return false;
			}
			if (this.videoChatChanges != chatEventLogFilters.videoChatChanges) {
				return false;
			}
			if (this.forumChanges != chatEventLogFilters.forumChanges) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.messageEdits);
			return result;
		}
	}

	/**
	 * Contains a list of chat events.
	**/
	public static final class ChatEvents extends Object {


		/**
		 * List of events.
		**/
		public ChatEvent[] events;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -585329664;

		/**
		 * Contains a list of chat events.
		**/
		public ChatEvents() {}

		/**
		 * Contains a list of chat events.
		 *
		 * @param events List of events.
		**/
		public ChatEvents(ChatEvent[] events) {
			this.events = events;
		}

		/**
		 * Contains a list of chat events.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatEvents(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.events = new ChatEvent[input.readInt()];
				for (int i = 0; i < this.events.length; i++) {
					if (ChatEvent.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.events[i] = new ChatEvent(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatEvents.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatEvents.CONSTRUCTOR);
			if (this.events == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.events.length);
				for (int i = 0; i < this.events.length; i++) {
					this.events[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatEvents chatEvents = (ChatEvents) o;
			if (!Arrays.equals(this.events, chatEvents.events)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.events);
		}
	}

	/**
	 * Represents a folder for user chats.
	**/
	public static final class ChatFolder extends Object {


		/**
		 * The title of the folder; 1-12 characters without line feeds.
		**/
		public String title;

		/**
		 * The chosen icon for the chat folder; may be null. If null, use getChatFolderDefaultIconName to get default icon name for the folder.
		**/
		public ChatFolderIcon icon;

		/**
		 * True, if at least one link has been created for the folder.
		**/
		public boolean isShareable;

		/**
		 * The chat identifiers of pinned chats in the folder. There can be up to getOption(&quot;chat_folder_chosen_chat_count_max&quot;) pinned and always included non-secret chats and the same number of secret chats, but the limit can be increased with Telegram Premium.
		**/
		public long[] pinnedChatIds;

		/**
		 * The chat identifiers of always included chats in the folder. There can be up to getOption(&quot;chat_folder_chosen_chat_count_max&quot;) pinned and always included non-secret chats and the same number of secret chats, but the limit can be increased with Telegram Premium.
		**/
		public long[] includedChatIds;

		/**
		 * The chat identifiers of always excluded chats in the folder. There can be up to getOption(&quot;chat_folder_chosen_chat_count_max&quot;) always excluded non-secret chats and the same number of secret chats, but the limit can be increased with Telegram Premium.
		**/
		public long[] excludedChatIds;

		/**
		 * True, if muted chats need to be excluded.
		**/
		public boolean excludeMuted;

		/**
		 * True, if read chats need to be excluded.
		**/
		public boolean excludeRead;

		/**
		 * True, if archived chats need to be excluded.
		**/
		public boolean excludeArchived;

		/**
		 * True, if contacts need to be included.
		**/
		public boolean includeContacts;

		/**
		 * True, if non-contact users need to be included.
		**/
		public boolean includeNonContacts;

		/**
		 * True, if bots need to be included.
		**/
		public boolean includeBots;

		/**
		 * True, if basic groups and supergroups need to be included.
		**/
		public boolean includeGroups;

		/**
		 * True, if channels need to be included.
		**/
		public boolean includeChannels;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -459081051;

		/**
		 * Represents a folder for user chats.
		**/
		public ChatFolder() {}

		/**
		 * Represents a folder for user chats.
		 *
		 * @param title The title of the folder; 1-12 characters without line feeds.
		 * @param icon The chosen icon for the chat folder; may be null. If null, use getChatFolderDefaultIconName to get default icon name for the folder.
		 * @param isShareable True, if at least one link has been created for the folder.
		 * @param pinnedChatIds The chat identifiers of pinned chats in the folder. There can be up to getOption(&quot;chat_folder_chosen_chat_count_max&quot;) pinned and always included non-secret chats and the same number of secret chats, but the limit can be increased with Telegram Premium.
		 * @param includedChatIds The chat identifiers of always included chats in the folder. There can be up to getOption(&quot;chat_folder_chosen_chat_count_max&quot;) pinned and always included non-secret chats and the same number of secret chats, but the limit can be increased with Telegram Premium.
		 * @param excludedChatIds The chat identifiers of always excluded chats in the folder. There can be up to getOption(&quot;chat_folder_chosen_chat_count_max&quot;) always excluded non-secret chats and the same number of secret chats, but the limit can be increased with Telegram Premium.
		 * @param excludeMuted True, if muted chats need to be excluded.
		 * @param excludeRead True, if read chats need to be excluded.
		 * @param excludeArchived True, if archived chats need to be excluded.
		 * @param includeContacts True, if contacts need to be included.
		 * @param includeNonContacts True, if non-contact users need to be included.
		 * @param includeBots True, if bots need to be included.
		 * @param includeGroups True, if basic groups and supergroups need to be included.
		 * @param includeChannels True, if channels need to be included.
		**/
		public ChatFolder(String title,
				ChatFolderIcon icon,
				boolean isShareable,
				long[] pinnedChatIds,
				long[] includedChatIds,
				long[] excludedChatIds,
				boolean excludeMuted,
				boolean excludeRead,
				boolean excludeArchived,
				boolean includeContacts,
				boolean includeNonContacts,
				boolean includeBots,
				boolean includeGroups,
				boolean includeChannels) {
			this.title = title;
			this.icon = icon;
			this.isShareable = isShareable;
			this.pinnedChatIds = pinnedChatIds;
			this.includedChatIds = includedChatIds;
			this.excludedChatIds = excludedChatIds;
			this.excludeMuted = excludeMuted;
			this.excludeRead = excludeRead;
			this.excludeArchived = excludeArchived;
			this.includeContacts = includeContacts;
			this.includeNonContacts = includeNonContacts;
			this.includeBots = includeBots;
			this.includeGroups = includeGroups;
			this.includeChannels = includeChannels;
		}

		/**
		 * Represents a folder for user chats.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatFolder(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (ChatFolderIcon.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.icon = new ChatFolderIcon(input);
			}
			this.isShareable = input.readBoolean();
			if (input.readBoolean()) {
				this.pinnedChatIds = new long[input.readInt()];
				for (int i = 0; i < this.pinnedChatIds.length; i++) {
					this.pinnedChatIds[i] = input.readLong();
				}
			}
			if (input.readBoolean()) {
				this.includedChatIds = new long[input.readInt()];
				for (int i = 0; i < this.includedChatIds.length; i++) {
					this.includedChatIds[i] = input.readLong();
				}
			}
			if (input.readBoolean()) {
				this.excludedChatIds = new long[input.readInt()];
				for (int i = 0; i < this.excludedChatIds.length; i++) {
					this.excludedChatIds[i] = input.readLong();
				}
			}
			this.excludeMuted = input.readBoolean();
			this.excludeRead = input.readBoolean();
			this.excludeArchived = input.readBoolean();
			this.includeContacts = input.readBoolean();
			this.includeNonContacts = input.readBoolean();
			this.includeBots = input.readBoolean();
			this.includeGroups = input.readBoolean();
			this.includeChannels = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatFolder.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatFolder.CONSTRUCTOR);
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
			if (this.icon == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.icon.serialize(output);
			}
			output.writeBoolean(this.isShareable);
			if (this.pinnedChatIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.pinnedChatIds.length);
				for (int i = 0; i < this.pinnedChatIds.length; i++) {
					output.writeLong(this.pinnedChatIds[i]);
				}
			}
			if (this.includedChatIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.includedChatIds.length);
				for (int i = 0; i < this.includedChatIds.length; i++) {
					output.writeLong(this.includedChatIds[i]);
				}
			}
			if (this.excludedChatIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.excludedChatIds.length);
				for (int i = 0; i < this.excludedChatIds.length; i++) {
					output.writeLong(this.excludedChatIds[i]);
				}
			}
			output.writeBoolean(this.excludeMuted);
			output.writeBoolean(this.excludeRead);
			output.writeBoolean(this.excludeArchived);
			output.writeBoolean(this.includeContacts);
			output.writeBoolean(this.includeNonContacts);
			output.writeBoolean(this.includeBots);
			output.writeBoolean(this.includeGroups);
			output.writeBoolean(this.includeChannels);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatFolder chatFolder = (ChatFolder) o;
			if (this.title != chatFolder.title) {
				return false;
			}
			if (!Objects.equals(this.icon, chatFolder.icon)) {
				return false;
			}
			if (this.isShareable != chatFolder.isShareable) {
				return false;
			}
			if (!Arrays.equals(this.pinnedChatIds, chatFolder.pinnedChatIds)) {
				return false;
			}
			if (!Arrays.equals(this.includedChatIds, chatFolder.includedChatIds)) {
				return false;
			}
			if (!Arrays.equals(this.excludedChatIds, chatFolder.excludedChatIds)) {
				return false;
			}
			if (this.excludeMuted != chatFolder.excludeMuted) {
				return false;
			}
			if (this.excludeRead != chatFolder.excludeRead) {
				return false;
			}
			if (this.excludeArchived != chatFolder.excludeArchived) {
				return false;
			}
			if (this.includeContacts != chatFolder.includeContacts) {
				return false;
			}
			if (this.includeNonContacts != chatFolder.includeNonContacts) {
				return false;
			}
			if (this.includeBots != chatFolder.includeBots) {
				return false;
			}
			if (this.includeGroups != chatFolder.includeGroups) {
				return false;
			}
			if (this.includeChannels != chatFolder.includeChannels) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isShareable);
			result = result * 31 + (this.title == null ? 0 : this.title.hashCode());
			result = result * 31 + (this.icon == null ? 0 : this.icon.hashCode());
			result = result * 31 + (Arrays.hashCode(this.pinnedChatIds));
			result = result * 31 + (Arrays.hashCode(this.includedChatIds));
			result = result * 31 + (Arrays.hashCode(this.excludedChatIds));
			return result;
		}
	}

	/**
	 * Represents an icon for a chat folder.
	**/
	public static final class ChatFolderIcon extends Object {


		/**
		 * The chosen icon name for short folder representation; one of &quot;All&quot;, &quot;Unread&quot;, &quot;Unmuted&quot;, &quot;Bots&quot;, &quot;Channels&quot;, &quot;Groups&quot;, &quot;Private&quot;, &quot;Custom&quot;, &quot;Setup&quot;, &quot;Cat&quot;, &quot;Crown&quot;, &quot;Favorite&quot;, &quot;Flower&quot;, &quot;Game&quot;, &quot;Home&quot;, &quot;Love&quot;, &quot;Mask&quot;, &quot;Party&quot;, &quot;Sport&quot;, &quot;Study&quot;, &quot;Trade&quot;, &quot;Travel&quot;, &quot;Work&quot;, &quot;Airplane&quot;, &quot;Book&quot;, &quot;Light&quot;, &quot;Like&quot;, &quot;Money&quot;, &quot;Note&quot;, &quot;Palette&quot;.
		**/
		public String name;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -146104090;

		/**
		 * Represents an icon for a chat folder.
		**/
		public ChatFolderIcon() {}

		/**
		 * Represents an icon for a chat folder.
		 *
		 * @param name The chosen icon name for short folder representation; one of &quot;All&quot;, &quot;Unread&quot;, &quot;Unmuted&quot;, &quot;Bots&quot;, &quot;Channels&quot;, &quot;Groups&quot;, &quot;Private&quot;, &quot;Custom&quot;, &quot;Setup&quot;, &quot;Cat&quot;, &quot;Crown&quot;, &quot;Favorite&quot;, &quot;Flower&quot;, &quot;Game&quot;, &quot;Home&quot;, &quot;Love&quot;, &quot;Mask&quot;, &quot;Party&quot;, &quot;Sport&quot;, &quot;Study&quot;, &quot;Trade&quot;, &quot;Travel&quot;, &quot;Work&quot;, &quot;Airplane&quot;, &quot;Book&quot;, &quot;Light&quot;, &quot;Like&quot;, &quot;Money&quot;, &quot;Note&quot;, &quot;Palette&quot;.
		**/
		public ChatFolderIcon(String name) {
			this.name = name;
		}

		/**
		 * Represents an icon for a chat folder.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatFolderIcon(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] nameTmp = new byte[input.readInt()];
				input.readFully(nameTmp);
				this.name = new String(nameTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatFolderIcon.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatFolderIcon.CONSTRUCTOR);
			if (this.name == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nameTmp = this.name.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nameTmp.length);
				output.write(nameTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatFolderIcon chatFolderIcon = (ChatFolderIcon) o;
			if (this.name != chatFolderIcon.name) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.name == null ? 0 : this.name.hashCode();
		}
	}

	/**
	 * Contains basic information about a chat folder.
	**/
	public static final class ChatFolderInfo extends Object {


		/**
		 * Unique chat folder identifier.
		**/
		public int id;

		/**
		 * The title of the folder; 1-12 characters without line feeds.
		**/
		public String title;

		/**
		 * The chosen or default icon for the chat folder.
		**/
		public ChatFolderIcon icon;

		/**
		 * True, if the chat folder has invite links created by the current user.
		**/
		public boolean hasMyInviteLinks;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 336032325;

		/**
		 * Contains basic information about a chat folder.
		**/
		public ChatFolderInfo() {}

		/**
		 * Contains basic information about a chat folder.
		 *
		 * @param id Unique chat folder identifier.
		 * @param title The title of the folder; 1-12 characters without line feeds.
		 * @param icon The chosen or default icon for the chat folder.
		 * @param hasMyInviteLinks True, if the chat folder has invite links created by the current user.
		**/
		public ChatFolderInfo(int id,
				String title,
				ChatFolderIcon icon,
				boolean hasMyInviteLinks) {
			this.id = id;
			this.title = title;
			this.icon = icon;
			this.hasMyInviteLinks = hasMyInviteLinks;
		}

		/**
		 * Contains basic information about a chat folder.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatFolderInfo(DataInput input) throws IOException {
			this.id = input.readInt();
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (ChatFolderIcon.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.icon = new ChatFolderIcon(input);
			}
			this.hasMyInviteLinks = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatFolderInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatFolderInfo.CONSTRUCTOR);
			output.writeInt(this.id);
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
			if (this.icon == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.icon.serialize(output);
			}
			output.writeBoolean(this.hasMyInviteLinks);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatFolderInfo chatFolderInfo = (ChatFolderInfo) o;
			if (this.id != chatFolderInfo.id) {
				return false;
			}
			if (this.title != chatFolderInfo.title) {
				return false;
			}
			if (!Objects.equals(this.icon, chatFolderInfo.icon)) {
				return false;
			}
			if (this.hasMyInviteLinks != chatFolderInfo.hasMyInviteLinks) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.id);
			result = result * 31 + (this.title == null ? 0 : this.title.hashCode());
			result = result * 31 + (this.icon == null ? 0 : this.icon.hashCode());
			return result;
		}
	}

	/**
	 * Contains a chat folder invite link.
	**/
	public static final class ChatFolderInviteLink extends Object {


		/**
		 * The chat folder invite link.
		**/
		public String inviteLink;

		/**
		 * Name of the link.
		**/
		public String name;

		/**
		 * Identifiers of chats, included in the link.
		**/
		public long[] chatIds;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 493969661;

		/**
		 * Contains a chat folder invite link.
		**/
		public ChatFolderInviteLink() {}

		/**
		 * Contains a chat folder invite link.
		 *
		 * @param inviteLink The chat folder invite link.
		 * @param name Name of the link.
		 * @param chatIds Identifiers of chats, included in the link.
		**/
		public ChatFolderInviteLink(String inviteLink, String name, long[] chatIds) {
			this.inviteLink = inviteLink;
			this.name = name;
			this.chatIds = chatIds;
		}

		/**
		 * Contains a chat folder invite link.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatFolderInviteLink(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] inviteLinkTmp = new byte[input.readInt()];
				input.readFully(inviteLinkTmp);
				this.inviteLink = new String(inviteLinkTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] nameTmp = new byte[input.readInt()];
				input.readFully(nameTmp);
				this.name = new String(nameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				this.chatIds = new long[input.readInt()];
				for (int i = 0; i < this.chatIds.length; i++) {
					this.chatIds[i] = input.readLong();
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatFolderInviteLink.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatFolderInviteLink.CONSTRUCTOR);
			if (this.inviteLink == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] inviteLinkTmp = this.inviteLink.getBytes(StandardCharsets.UTF_8);
				output.writeInt(inviteLinkTmp.length);
				output.write(inviteLinkTmp);
			}
			if (this.name == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nameTmp = this.name.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nameTmp.length);
				output.write(nameTmp);
			}
			if (this.chatIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.chatIds.length);
				for (int i = 0; i < this.chatIds.length; i++) {
					output.writeLong(this.chatIds[i]);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatFolderInviteLink chatFolderInviteLink = (ChatFolderInviteLink) o;
			if (this.inviteLink != chatFolderInviteLink.inviteLink) {
				return false;
			}
			if (this.name != chatFolderInviteLink.name) {
				return false;
			}
			if (!Arrays.equals(this.chatIds, chatFolderInviteLink.chatIds)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.inviteLink == null ? 0 : this.inviteLink.hashCode();
			result = result * 31 + (this.name == null ? 0 : this.name.hashCode());
			result = result * 31 + (Arrays.hashCode(this.chatIds));
			return result;
		}
	}

	/**
	 * Contains information about an invite link to a chat folder.
	**/
	public static final class ChatFolderInviteLinkInfo extends Object {


		/**
		 * Basic information about the chat folder; chat folder identifier will be 0 if the user didn&#039;t have the chat folder yet.
		**/
		public ChatFolderInfo chatFolderInfo;

		/**
		 * Identifiers of the chats from the link, which aren&#039;t added to the folder yet.
		**/
		public long[] missingChatIds;

		/**
		 * Identifiers of the chats from the link, which are added to the folder already.
		**/
		public long[] addedChatIds;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1119450395;

		/**
		 * Contains information about an invite link to a chat folder.
		**/
		public ChatFolderInviteLinkInfo() {}

		/**
		 * Contains information about an invite link to a chat folder.
		 *
		 * @param chatFolderInfo Basic information about the chat folder; chat folder identifier will be 0 if the user didn&#039;t have the chat folder yet.
		 * @param missingChatIds Identifiers of the chats from the link, which aren&#039;t added to the folder yet.
		 * @param addedChatIds Identifiers of the chats from the link, which are added to the folder already.
		**/
		public ChatFolderInviteLinkInfo(ChatFolderInfo chatFolderInfo,
				long[] missingChatIds,
				long[] addedChatIds) {
			this.chatFolderInfo = chatFolderInfo;
			this.missingChatIds = missingChatIds;
			this.addedChatIds = addedChatIds;
		}

		/**
		 * Contains information about an invite link to a chat folder.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatFolderInviteLinkInfo(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (ChatFolderInfo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.chatFolderInfo = new ChatFolderInfo(input);
			}
			if (input.readBoolean()) {
				this.missingChatIds = new long[input.readInt()];
				for (int i = 0; i < this.missingChatIds.length; i++) {
					this.missingChatIds[i] = input.readLong();
				}
			}
			if (input.readBoolean()) {
				this.addedChatIds = new long[input.readInt()];
				for (int i = 0; i < this.addedChatIds.length; i++) {
					this.addedChatIds[i] = input.readLong();
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatFolderInviteLinkInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatFolderInviteLinkInfo.CONSTRUCTOR);
			if (this.chatFolderInfo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.chatFolderInfo.serialize(output);
			}
			if (this.missingChatIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.missingChatIds.length);
				for (int i = 0; i < this.missingChatIds.length; i++) {
					output.writeLong(this.missingChatIds[i]);
				}
			}
			if (this.addedChatIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.addedChatIds.length);
				for (int i = 0; i < this.addedChatIds.length; i++) {
					output.writeLong(this.addedChatIds[i]);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatFolderInviteLinkInfo chatFolderInviteLinkInfo = (ChatFolderInviteLinkInfo) o;
			if (!Objects.equals(this.chatFolderInfo, chatFolderInviteLinkInfo.chatFolderInfo)) {
				return false;
			}
			if (!Arrays.equals(this.missingChatIds, chatFolderInviteLinkInfo.missingChatIds)) {
				return false;
			}
			if (!Arrays.equals(this.addedChatIds, chatFolderInviteLinkInfo.addedChatIds)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.chatFolderInfo == null ? 0 : this.chatFolderInfo.hashCode();
			result = result * 31 + (Arrays.hashCode(this.missingChatIds));
			result = result * 31 + (Arrays.hashCode(this.addedChatIds));
			return result;
		}
	}

	/**
	 * Represents a list of chat folder invite links.
	**/
	public static final class ChatFolderInviteLinks extends Object {


		/**
		 * List of the invite links.
		**/
		public ChatFolderInviteLink[] inviteLinks;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1853351525;

		/**
		 * Represents a list of chat folder invite links.
		**/
		public ChatFolderInviteLinks() {}

		/**
		 * Represents a list of chat folder invite links.
		 *
		 * @param inviteLinks List of the invite links.
		**/
		public ChatFolderInviteLinks(ChatFolderInviteLink[] inviteLinks) {
			this.inviteLinks = inviteLinks;
		}

		/**
		 * Represents a list of chat folder invite links.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatFolderInviteLinks(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.inviteLinks = new ChatFolderInviteLink[input.readInt()];
				for (int i = 0; i < this.inviteLinks.length; i++) {
					if (ChatFolderInviteLink.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.inviteLinks[i] = new ChatFolderInviteLink(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatFolderInviteLinks.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatFolderInviteLinks.CONSTRUCTOR);
			if (this.inviteLinks == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.inviteLinks.length);
				for (int i = 0; i < this.inviteLinks.length; i++) {
					this.inviteLinks[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatFolderInviteLinks chatFolderInviteLinks = (ChatFolderInviteLinks) o;
			if (!Arrays.equals(this.inviteLinks, chatFolderInviteLinks.inviteLinks)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.inviteLinks);
		}
	}

	/**
	 * Contains a chat invite link.
	**/
	public static final class ChatInviteLink extends Object {


		/**
		 * Chat invite link.
		**/
		public String inviteLink;

		/**
		 * Name of the link.
		**/
		public String name;

		/**
		 * User identifier of an administrator created the link.
		**/
		public long creatorUserId;

		/**
		 * Point in time (Unix timestamp) when the link was created.
		**/
		public int date;

		/**
		 * Point in time (Unix timestamp) when the link was last edited; 0 if never or unknown.
		**/
		public int editDate;

		/**
		 * Point in time (Unix timestamp) when the link will expire; 0 if never.
		**/
		public int expirationDate;

		/**
		 * The maximum number of members, which can join the chat using the link simultaneously; 0 if not limited. Always 0 if the link requires approval.
		**/
		public int memberLimit;

		/**
		 * Number of chat members, which joined the chat using the link.
		**/
		public int memberCount;

		/**
		 * Number of pending join requests created using this link.
		**/
		public int pendingJoinRequestCount;

		/**
		 * True, if the link only creates join request. If true, total number of joining members will be unlimited.
		**/
		public boolean createsJoinRequest;

		/**
		 * True, if the link is primary. Primary invite link can&#039;t have name, expiration date, or usage limit. There is exactly one primary invite link for each administrator with canInviteUsers right at a given time.
		**/
		public boolean isPrimary;

		/**
		 * True, if the link was revoked.
		**/
		public boolean isRevoked;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -205812476;

		/**
		 * Contains a chat invite link.
		**/
		public ChatInviteLink() {}

		/**
		 * Contains a chat invite link.
		 *
		 * @param inviteLink Chat invite link.
		 * @param name Name of the link.
		 * @param creatorUserId User identifier of an administrator created the link.
		 * @param date Point in time (Unix timestamp) when the link was created.
		 * @param editDate Point in time (Unix timestamp) when the link was last edited; 0 if never or unknown.
		 * @param expirationDate Point in time (Unix timestamp) when the link will expire; 0 if never.
		 * @param memberLimit The maximum number of members, which can join the chat using the link simultaneously; 0 if not limited. Always 0 if the link requires approval.
		 * @param memberCount Number of chat members, which joined the chat using the link.
		 * @param pendingJoinRequestCount Number of pending join requests created using this link.
		 * @param createsJoinRequest True, if the link only creates join request. If true, total number of joining members will be unlimited.
		 * @param isPrimary True, if the link is primary. Primary invite link can&#039;t have name, expiration date, or usage limit. There is exactly one primary invite link for each administrator with canInviteUsers right at a given time.
		 * @param isRevoked True, if the link was revoked.
		**/
		public ChatInviteLink(String inviteLink,
				String name,
				long creatorUserId,
				int date,
				int editDate,
				int expirationDate,
				int memberLimit,
				int memberCount,
				int pendingJoinRequestCount,
				boolean createsJoinRequest,
				boolean isPrimary,
				boolean isRevoked) {
			this.inviteLink = inviteLink;
			this.name = name;
			this.creatorUserId = creatorUserId;
			this.date = date;
			this.editDate = editDate;
			this.expirationDate = expirationDate;
			this.memberLimit = memberLimit;
			this.memberCount = memberCount;
			this.pendingJoinRequestCount = pendingJoinRequestCount;
			this.createsJoinRequest = createsJoinRequest;
			this.isPrimary = isPrimary;
			this.isRevoked = isRevoked;
		}

		/**
		 * Contains a chat invite link.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatInviteLink(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] inviteLinkTmp = new byte[input.readInt()];
				input.readFully(inviteLinkTmp);
				this.inviteLink = new String(inviteLinkTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] nameTmp = new byte[input.readInt()];
				input.readFully(nameTmp);
				this.name = new String(nameTmp, StandardCharsets.UTF_8);
			}
			this.creatorUserId = input.readLong();
			this.date = input.readInt();
			this.editDate = input.readInt();
			this.expirationDate = input.readInt();
			this.memberLimit = input.readInt();
			this.memberCount = input.readInt();
			this.pendingJoinRequestCount = input.readInt();
			this.createsJoinRequest = input.readBoolean();
			this.isPrimary = input.readBoolean();
			this.isRevoked = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatInviteLink.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatInviteLink.CONSTRUCTOR);
			if (this.inviteLink == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] inviteLinkTmp = this.inviteLink.getBytes(StandardCharsets.UTF_8);
				output.writeInt(inviteLinkTmp.length);
				output.write(inviteLinkTmp);
			}
			if (this.name == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nameTmp = this.name.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nameTmp.length);
				output.write(nameTmp);
			}
			output.writeLong(this.creatorUserId);
			output.writeInt(this.date);
			output.writeInt(this.editDate);
			output.writeInt(this.expirationDate);
			output.writeInt(this.memberLimit);
			output.writeInt(this.memberCount);
			output.writeInt(this.pendingJoinRequestCount);
			output.writeBoolean(this.createsJoinRequest);
			output.writeBoolean(this.isPrimary);
			output.writeBoolean(this.isRevoked);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatInviteLink chatInviteLink = (ChatInviteLink) o;
			if (this.inviteLink != chatInviteLink.inviteLink) {
				return false;
			}
			if (this.name != chatInviteLink.name) {
				return false;
			}
			if (this.creatorUserId != chatInviteLink.creatorUserId) {
				return false;
			}
			if (this.date != chatInviteLink.date) {
				return false;
			}
			if (this.editDate != chatInviteLink.editDate) {
				return false;
			}
			if (this.expirationDate != chatInviteLink.expirationDate) {
				return false;
			}
			if (this.memberLimit != chatInviteLink.memberLimit) {
				return false;
			}
			if (this.memberCount != chatInviteLink.memberCount) {
				return false;
			}
			if (this.pendingJoinRequestCount != chatInviteLink.pendingJoinRequestCount) {
				return false;
			}
			if (this.createsJoinRequest != chatInviteLink.createsJoinRequest) {
				return false;
			}
			if (this.isPrimary != chatInviteLink.isPrimary) {
				return false;
			}
			if (this.isRevoked != chatInviteLink.isRevoked) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.creatorUserId);
			result = result * 31 + (this.inviteLink == null ? 0 : this.inviteLink.hashCode());
			result = result * 31 + (this.name == null ? 0 : this.name.hashCode());
			return result;
		}
	}

	/**
	 * Describes a chat administrator with a number of active and revoked
	 * chat invite links.
	**/
	public static final class ChatInviteLinkCount extends Object {


		/**
		 * Administrator&#039;s user identifier.
		**/
		public long userId;

		/**
		 * Number of active invite links.
		**/
		public int inviteLinkCount;

		/**
		 * Number of revoked invite links.
		**/
		public int revokedInviteLinkCount;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1021999210;

		/**
		 * Describes a chat administrator with a number of active and revoked chat invite links.
		**/
		public ChatInviteLinkCount() {}

		/**
		 * Describes a chat administrator with a number of active and revoked chat invite links.
		 *
		 * @param userId Administrator&#039;s user identifier.
		 * @param inviteLinkCount Number of active invite links.
		 * @param revokedInviteLinkCount Number of revoked invite links.
		**/
		public ChatInviteLinkCount(long userId, int inviteLinkCount, int revokedInviteLinkCount) {
			this.userId = userId;
			this.inviteLinkCount = inviteLinkCount;
			this.revokedInviteLinkCount = revokedInviteLinkCount;
		}

		/**
		 * Describes a chat administrator with a number of active and revoked chat invite links.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatInviteLinkCount(DataInput input) throws IOException {
			this.userId = input.readLong();
			this.inviteLinkCount = input.readInt();
			this.revokedInviteLinkCount = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatInviteLinkCount.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatInviteLinkCount.CONSTRUCTOR);
			output.writeLong(this.userId);
			output.writeInt(this.inviteLinkCount);
			output.writeInt(this.revokedInviteLinkCount);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatInviteLinkCount chatInviteLinkCount = (ChatInviteLinkCount) o;
			if (this.userId != chatInviteLinkCount.userId) {
				return false;
			}
			if (this.inviteLinkCount != chatInviteLinkCount.inviteLinkCount) {
				return false;
			}
			if (this.revokedInviteLinkCount != chatInviteLinkCount.revokedInviteLinkCount) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.userId);
			return result;
		}
	}

	/**
	 * Contains a list of chat invite link counts.
	**/
	public static final class ChatInviteLinkCounts extends Object {


		/**
		 * List of invite link counts.
		**/
		public ChatInviteLinkCount[] inviteLinkCounts;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 920326637;

		/**
		 * Contains a list of chat invite link counts.
		**/
		public ChatInviteLinkCounts() {}

		/**
		 * Contains a list of chat invite link counts.
		 *
		 * @param inviteLinkCounts List of invite link counts.
		**/
		public ChatInviteLinkCounts(ChatInviteLinkCount[] inviteLinkCounts) {
			this.inviteLinkCounts = inviteLinkCounts;
		}

		/**
		 * Contains a list of chat invite link counts.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatInviteLinkCounts(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.inviteLinkCounts = new ChatInviteLinkCount[input.readInt()];
				for (int i = 0; i < this.inviteLinkCounts.length; i++) {
					if (ChatInviteLinkCount.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.inviteLinkCounts[i] = new ChatInviteLinkCount(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatInviteLinkCounts.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatInviteLinkCounts.CONSTRUCTOR);
			if (this.inviteLinkCounts == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.inviteLinkCounts.length);
				for (int i = 0; i < this.inviteLinkCounts.length; i++) {
					this.inviteLinkCounts[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatInviteLinkCounts chatInviteLinkCounts = (ChatInviteLinkCounts) o;
			if (!Arrays.equals(this.inviteLinkCounts, chatInviteLinkCounts.inviteLinkCounts)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.inviteLinkCounts);
		}
	}

	/**
	 * Contains information about a chat invite link.
	**/
	public static final class ChatInviteLinkInfo extends Object {


		/**
		 * Chat identifier of the invite link; 0 if the user has no access to the chat before joining.
		**/
		public long chatId;

		/**
		 * If non-zero, the amount of time for which read access to the chat will remain available, in seconds.
		**/
		public int accessibleFor;

		/**
		 * Type of the chat.
		**/
		public ChatType type;

		/**
		 * Title of the chat.
		**/
		public String title;

		/**
		 * Chat photo; may be null.
		**/
		public ChatPhotoInfo photo;

		/**
		 * Chat description.
		**/
		public String description;

		/**
		 * Number of members in the chat.
		**/
		public int memberCount;

		/**
		 * User identifiers of some chat members that may be known to the current user.
		**/
		public long[] memberUserIds;

		/**
		 * True, if the link only creates join request.
		**/
		public boolean createsJoinRequest;

		/**
		 * True, if the chat is a public supergroup or channel, i.e. it has a username or it is a location-based supergroup.
		**/
		public boolean isPublic;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 546234276;

		/**
		 * Contains information about a chat invite link.
		**/
		public ChatInviteLinkInfo() {}

		/**
		 * Contains information about a chat invite link.
		 *
		 * @param chatId Chat identifier of the invite link; 0 if the user has no access to the chat before joining.
		 * @param accessibleFor If non-zero, the amount of time for which read access to the chat will remain available, in seconds.
		 * @param type Type of the chat.
		 * @param title Title of the chat.
		 * @param photo Chat photo; may be null.
		 * @param description Chat description.
		 * @param memberCount Number of members in the chat.
		 * @param memberUserIds User identifiers of some chat members that may be known to the current user.
		 * @param createsJoinRequest True, if the link only creates join request.
		 * @param isPublic True, if the chat is a public supergroup or channel, i.e. it has a username or it is a location-based supergroup.
		**/
		public ChatInviteLinkInfo(long chatId,
				int accessibleFor,
				ChatType type,
				String title,
				ChatPhotoInfo photo,
				String description,
				int memberCount,
				long[] memberUserIds,
				boolean createsJoinRequest,
				boolean isPublic) {
			this.chatId = chatId;
			this.accessibleFor = accessibleFor;
			this.type = type;
			this.title = title;
			this.photo = photo;
			this.description = description;
			this.memberCount = memberCount;
			this.memberUserIds = memberUserIds;
			this.createsJoinRequest = createsJoinRequest;
			this.isPublic = isPublic;
		}

		/**
		 * Contains information about a chat invite link.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatInviteLinkInfo(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.accessibleFor = input.readInt();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ChatTypePrivate.CONSTRUCTOR: this.type = new ChatTypePrivate(input); break;
					case ChatTypeBasicGroup.CONSTRUCTOR: this.type = new ChatTypeBasicGroup(input); break;
					case ChatTypeSupergroup.CONSTRUCTOR: this.type = new ChatTypeSupergroup(input); break;
					case ChatTypeSecret.CONSTRUCTOR: this.type = new ChatTypeSecret(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (ChatPhotoInfo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.photo = new ChatPhotoInfo(input);
			}
			if (input.readBoolean()) {
				byte[] descriptionTmp = new byte[input.readInt()];
				input.readFully(descriptionTmp);
				this.description = new String(descriptionTmp, StandardCharsets.UTF_8);
			}
			this.memberCount = input.readInt();
			if (input.readBoolean()) {
				this.memberUserIds = new long[input.readInt()];
				for (int i = 0; i < this.memberUserIds.length; i++) {
					this.memberUserIds[i] = input.readLong();
				}
			}
			this.createsJoinRequest = input.readBoolean();
			this.isPublic = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatInviteLinkInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatInviteLinkInfo.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeInt(this.accessibleFor);
			if (this.type == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.type.serialize(output);
			}
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
			if (this.photo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.photo.serialize(output);
			}
			if (this.description == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] descriptionTmp = this.description.getBytes(StandardCharsets.UTF_8);
				output.writeInt(descriptionTmp.length);
				output.write(descriptionTmp);
			}
			output.writeInt(this.memberCount);
			if (this.memberUserIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.memberUserIds.length);
				for (int i = 0; i < this.memberUserIds.length; i++) {
					output.writeLong(this.memberUserIds[i]);
				}
			}
			output.writeBoolean(this.createsJoinRequest);
			output.writeBoolean(this.isPublic);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatInviteLinkInfo chatInviteLinkInfo = (ChatInviteLinkInfo) o;
			if (this.chatId != chatInviteLinkInfo.chatId) {
				return false;
			}
			if (this.accessibleFor != chatInviteLinkInfo.accessibleFor) {
				return false;
			}
			if (!Objects.equals(this.type, chatInviteLinkInfo.type)) {
				return false;
			}
			if (this.title != chatInviteLinkInfo.title) {
				return false;
			}
			if (!Objects.equals(this.photo, chatInviteLinkInfo.photo)) {
				return false;
			}
			if (this.description != chatInviteLinkInfo.description) {
				return false;
			}
			if (this.memberCount != chatInviteLinkInfo.memberCount) {
				return false;
			}
			if (!Arrays.equals(this.memberUserIds, chatInviteLinkInfo.memberUserIds)) {
				return false;
			}
			if (this.createsJoinRequest != chatInviteLinkInfo.createsJoinRequest) {
				return false;
			}
			if (this.isPublic != chatInviteLinkInfo.isPublic) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.type == null ? 0 : this.type.hashCode());
			result = result * 31 + (this.title == null ? 0 : this.title.hashCode());
			result = result * 31 + (this.photo == null ? 0 : this.photo.hashCode());
			result = result * 31 + (this.description == null ? 0 : this.description.hashCode());
			result = result * 31 + (Arrays.hashCode(this.memberUserIds));
			return result;
		}
	}

	/**
	 * Describes a chat member joined a chat via an invite link.
	**/
	public static final class ChatInviteLinkMember extends Object {


		/**
		 * User identifier.
		**/
		public long userId;

		/**
		 * Point in time (Unix timestamp) when the user joined the chat.
		**/
		public int joinedChatDate;

		/**
		 * True, if the user has joined the chat using an invite link for a chat folder.
		**/
		public boolean viaChatFolderInviteLink;

		/**
		 * User identifier of the chat administrator, approved user join request.
		**/
		public long approverUserId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 29156795;

		/**
		 * Describes a chat member joined a chat via an invite link.
		**/
		public ChatInviteLinkMember() {}

		/**
		 * Describes a chat member joined a chat via an invite link.
		 *
		 * @param userId User identifier.
		 * @param joinedChatDate Point in time (Unix timestamp) when the user joined the chat.
		 * @param viaChatFolderInviteLink True, if the user has joined the chat using an invite link for a chat folder.
		 * @param approverUserId User identifier of the chat administrator, approved user join request.
		**/
		public ChatInviteLinkMember(long userId,
				int joinedChatDate,
				boolean viaChatFolderInviteLink,
				long approverUserId) {
			this.userId = userId;
			this.joinedChatDate = joinedChatDate;
			this.viaChatFolderInviteLink = viaChatFolderInviteLink;
			this.approverUserId = approverUserId;
		}

		/**
		 * Describes a chat member joined a chat via an invite link.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatInviteLinkMember(DataInput input) throws IOException {
			this.userId = input.readLong();
			this.joinedChatDate = input.readInt();
			this.viaChatFolderInviteLink = input.readBoolean();
			this.approverUserId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatInviteLinkMember.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatInviteLinkMember.CONSTRUCTOR);
			output.writeLong(this.userId);
			output.writeInt(this.joinedChatDate);
			output.writeBoolean(this.viaChatFolderInviteLink);
			output.writeLong(this.approverUserId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatInviteLinkMember chatInviteLinkMember = (ChatInviteLinkMember) o;
			if (this.userId != chatInviteLinkMember.userId) {
				return false;
			}
			if (this.joinedChatDate != chatInviteLinkMember.joinedChatDate) {
				return false;
			}
			if (this.viaChatFolderInviteLink != chatInviteLinkMember.viaChatFolderInviteLink) {
				return false;
			}
			if (this.approverUserId != chatInviteLinkMember.approverUserId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.userId);
			return result;
		}
	}

	/**
	 * Contains a list of chat members joined a chat via an invite link.
	**/
	public static final class ChatInviteLinkMembers extends Object {


		/**
		 * Approximate total number of chat members found.
		**/
		public int totalCount;

		/**
		 * List of chat members, joined a chat via an invite link.
		**/
		public ChatInviteLinkMember[] members;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 315635051;

		/**
		 * Contains a list of chat members joined a chat via an invite link.
		**/
		public ChatInviteLinkMembers() {}

		/**
		 * Contains a list of chat members joined a chat via an invite link.
		 *
		 * @param totalCount Approximate total number of chat members found.
		 * @param members List of chat members, joined a chat via an invite link.
		**/
		public ChatInviteLinkMembers(int totalCount, ChatInviteLinkMember[] members) {
			this.totalCount = totalCount;
			this.members = members;
		}

		/**
		 * Contains a list of chat members joined a chat via an invite link.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatInviteLinkMembers(DataInput input) throws IOException {
			this.totalCount = input.readInt();
			if (input.readBoolean()) {
				this.members = new ChatInviteLinkMember[input.readInt()];
				for (int i = 0; i < this.members.length; i++) {
					if (ChatInviteLinkMember.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.members[i] = new ChatInviteLinkMember(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatInviteLinkMembers.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatInviteLinkMembers.CONSTRUCTOR);
			output.writeInt(this.totalCount);
			if (this.members == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.members.length);
				for (int i = 0; i < this.members.length; i++) {
					this.members[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatInviteLinkMembers chatInviteLinkMembers = (ChatInviteLinkMembers) o;
			if (this.totalCount != chatInviteLinkMembers.totalCount) {
				return false;
			}
			if (!Arrays.equals(this.members, chatInviteLinkMembers.members)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.totalCount);
			result = result * 31 + (Arrays.hashCode(this.members));
			return result;
		}
	}

	/**
	 * Contains a list of chat invite links.
	**/
	public static final class ChatInviteLinks extends Object {


		/**
		 * Approximate total number of chat invite links found.
		**/
		public int totalCount;

		/**
		 * List of invite links.
		**/
		public ChatInviteLink[] inviteLinks;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 112891427;

		/**
		 * Contains a list of chat invite links.
		**/
		public ChatInviteLinks() {}

		/**
		 * Contains a list of chat invite links.
		 *
		 * @param totalCount Approximate total number of chat invite links found.
		 * @param inviteLinks List of invite links.
		**/
		public ChatInviteLinks(int totalCount, ChatInviteLink[] inviteLinks) {
			this.totalCount = totalCount;
			this.inviteLinks = inviteLinks;
		}

		/**
		 * Contains a list of chat invite links.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatInviteLinks(DataInput input) throws IOException {
			this.totalCount = input.readInt();
			if (input.readBoolean()) {
				this.inviteLinks = new ChatInviteLink[input.readInt()];
				for (int i = 0; i < this.inviteLinks.length; i++) {
					if (ChatInviteLink.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.inviteLinks[i] = new ChatInviteLink(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatInviteLinks.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatInviteLinks.CONSTRUCTOR);
			output.writeInt(this.totalCount);
			if (this.inviteLinks == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.inviteLinks.length);
				for (int i = 0; i < this.inviteLinks.length; i++) {
					this.inviteLinks[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatInviteLinks chatInviteLinks = (ChatInviteLinks) o;
			if (this.totalCount != chatInviteLinks.totalCount) {
				return false;
			}
			if (!Arrays.equals(this.inviteLinks, chatInviteLinks.inviteLinks)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.totalCount);
			result = result * 31 + (Arrays.hashCode(this.inviteLinks));
			return result;
		}
	}

	/**
	 * Describes a user that sent a join request and waits for administrator
	 * approval.
	**/
	public static final class ChatJoinRequest extends Object {


		/**
		 * User identifier.
		**/
		public long userId;

		/**
		 * Point in time (Unix timestamp) when the user sent the join request.
		**/
		public int date;

		/**
		 * A short bio of the user.
		**/
		public String bio;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 59341416;

		/**
		 * Describes a user that sent a join request and waits for administrator approval.
		**/
		public ChatJoinRequest() {}

		/**
		 * Describes a user that sent a join request and waits for administrator approval.
		 *
		 * @param userId User identifier.
		 * @param date Point in time (Unix timestamp) when the user sent the join request.
		 * @param bio A short bio of the user.
		**/
		public ChatJoinRequest(long userId, int date, String bio) {
			this.userId = userId;
			this.date = date;
			this.bio = bio;
		}

		/**
		 * Describes a user that sent a join request and waits for administrator approval.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatJoinRequest(DataInput input) throws IOException {
			this.userId = input.readLong();
			this.date = input.readInt();
			if (input.readBoolean()) {
				byte[] bioTmp = new byte[input.readInt()];
				input.readFully(bioTmp);
				this.bio = new String(bioTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatJoinRequest.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatJoinRequest.CONSTRUCTOR);
			output.writeLong(this.userId);
			output.writeInt(this.date);
			if (this.bio == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] bioTmp = this.bio.getBytes(StandardCharsets.UTF_8);
				output.writeInt(bioTmp.length);
				output.write(bioTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatJoinRequest chatJoinRequest = (ChatJoinRequest) o;
			if (this.userId != chatJoinRequest.userId) {
				return false;
			}
			if (this.date != chatJoinRequest.date) {
				return false;
			}
			if (this.bio != chatJoinRequest.bio) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.userId);
			result = result * 31 + (this.bio == null ? 0 : this.bio.hashCode());
			return result;
		}
	}

	/**
	 * Contains a list of requests to join a chat.
	**/
	public static final class ChatJoinRequests extends Object {


		/**
		 * Approximate total number of requests found.
		**/
		public int totalCount;

		/**
		 * List of the requests.
		**/
		public ChatJoinRequest[] requests;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1291680519;

		/**
		 * Contains a list of requests to join a chat.
		**/
		public ChatJoinRequests() {}

		/**
		 * Contains a list of requests to join a chat.
		 *
		 * @param totalCount Approximate total number of requests found.
		 * @param requests List of the requests.
		**/
		public ChatJoinRequests(int totalCount, ChatJoinRequest[] requests) {
			this.totalCount = totalCount;
			this.requests = requests;
		}

		/**
		 * Contains a list of requests to join a chat.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatJoinRequests(DataInput input) throws IOException {
			this.totalCount = input.readInt();
			if (input.readBoolean()) {
				this.requests = new ChatJoinRequest[input.readInt()];
				for (int i = 0; i < this.requests.length; i++) {
					if (ChatJoinRequest.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.requests[i] = new ChatJoinRequest(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatJoinRequests.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatJoinRequests.CONSTRUCTOR);
			output.writeInt(this.totalCount);
			if (this.requests == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.requests.length);
				for (int i = 0; i < this.requests.length; i++) {
					this.requests[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatJoinRequests chatJoinRequests = (ChatJoinRequests) o;
			if (this.totalCount != chatJoinRequests.totalCount) {
				return false;
			}
			if (!Arrays.equals(this.requests, chatJoinRequests.requests)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.totalCount);
			result = result * 31 + (Arrays.hashCode(this.requests));
			return result;
		}
	}

	/**
	 * Contains information about pending join requests for a chat.
	**/
	public static final class ChatJoinRequestsInfo extends Object {


		/**
		 * Total number of pending join requests.
		**/
		public int totalCount;

		/**
		 * Identifiers of at most 3 users sent the newest pending join requests.
		**/
		public long[] userIds;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 888534463;

		/**
		 * Contains information about pending join requests for a chat.
		**/
		public ChatJoinRequestsInfo() {}

		/**
		 * Contains information about pending join requests for a chat.
		 *
		 * @param totalCount Total number of pending join requests.
		 * @param userIds Identifiers of at most 3 users sent the newest pending join requests.
		**/
		public ChatJoinRequestsInfo(int totalCount, long[] userIds) {
			this.totalCount = totalCount;
			this.userIds = userIds;
		}

		/**
		 * Contains information about pending join requests for a chat.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatJoinRequestsInfo(DataInput input) throws IOException {
			this.totalCount = input.readInt();
			if (input.readBoolean()) {
				this.userIds = new long[input.readInt()];
				for (int i = 0; i < this.userIds.length; i++) {
					this.userIds[i] = input.readLong();
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatJoinRequestsInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatJoinRequestsInfo.CONSTRUCTOR);
			output.writeInt(this.totalCount);
			if (this.userIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.userIds.length);
				for (int i = 0; i < this.userIds.length; i++) {
					output.writeLong(this.userIds[i]);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatJoinRequestsInfo chatJoinRequestsInfo = (ChatJoinRequestsInfo) o;
			if (this.totalCount != chatJoinRequestsInfo.totalCount) {
				return false;
			}
			if (!Arrays.equals(this.userIds, chatJoinRequestsInfo.userIds)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.totalCount);
			result = result * 31 + (Arrays.hashCode(this.userIds));
			return result;
		}
	}

	/**
	 * A main list of chats.
	**/
	public static final class ChatListMain extends ChatList {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -400991316;

		/**
		 * A main list of chats.
		**/
		public ChatListMain() {}

		/**
		 * A main list of chats.
		 *
		**/

		/**
		 * A main list of chats.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatListMain(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatListMain.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatListMain.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ChatListMain.CONSTRUCTOR;
		}
	}

	/**
	 * A list of chats usually located at the top of the main chat list.
	 * Unmuted chats are automatically moved from the Archive to the Main
	 * chat list when a new message arrives.
	**/
	public static final class ChatListArchive extends ChatList {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 362770115;

		/**
		 * A list of chats usually located at the top of the main chat list. Unmuted chats are automatically moved from the Archive to the Main chat list when a new message arrives.
		**/
		public ChatListArchive() {}

		/**
		 * A list of chats usually located at the top of the main chat list. Unmuted chats are automatically moved from the Archive to the Main chat list when a new message arrives.
		 *
		**/

		/**
		 * A list of chats usually located at the top of the main chat list. Unmuted chats are automatically moved from the Archive to the Main chat list when a new message arrives.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatListArchive(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatListArchive.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatListArchive.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ChatListArchive.CONSTRUCTOR;
		}
	}

	/**
	 * A list of chats added to a chat folder.
	**/
	public static final class ChatListFolder extends ChatList {


		/**
		 * Chat folder identifier.
		**/
		public int chatFolderId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 385760856;

		/**
		 * A list of chats added to a chat folder.
		**/
		public ChatListFolder() {}

		/**
		 * A list of chats added to a chat folder.
		 *
		 * @param chatFolderId Chat folder identifier.
		**/
		public ChatListFolder(int chatFolderId) {
			this.chatFolderId = chatFolderId;
		}

		/**
		 * A list of chats added to a chat folder.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatListFolder(DataInput input) throws IOException {
			this.chatFolderId = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatListFolder.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatListFolder.CONSTRUCTOR);
			output.writeInt(this.chatFolderId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatListFolder chatListFolder = (ChatListFolder) o;
			if (this.chatFolderId != chatListFolder.chatFolderId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.chatFolderId);
		}
	}

	/**
	 * Contains a list of chat lists.
	**/
	public static final class ChatLists extends Object {


		/**
		 * List of chat lists.
		**/
		public ChatList[] chatLists;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -258292771;

		/**
		 * Contains a list of chat lists.
		**/
		public ChatLists() {}

		/**
		 * Contains a list of chat lists.
		 *
		 * @param chatLists List of chat lists.
		**/
		public ChatLists(ChatList[] chatLists) {
			this.chatLists = chatLists;
		}

		/**
		 * Contains a list of chat lists.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatLists(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.chatLists = new ChatList[input.readInt()];
				for (int i = 0; i < this.chatLists.length; i++) {
					switch(input.readInt()) {
						case ChatListMain.CONSTRUCTOR: this.chatLists[i] = new ChatListMain(input); break;
						case ChatListArchive.CONSTRUCTOR: this.chatLists[i] = new ChatListArchive(input); break;
						case ChatListFolder.CONSTRUCTOR: this.chatLists[i] = new ChatListFolder(input); break;
						default: {
							throw new UnsupportedOperationException();
						}
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatLists.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatLists.CONSTRUCTOR);
			if (this.chatLists == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.chatLists.length);
				for (int i = 0; i < this.chatLists.length; i++) {
					this.chatLists[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatLists chatLists = (ChatLists) o;
			if (!Arrays.equals(this.chatLists, chatLists.chatLists)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.chatLists);
		}
	}

	/**
	 * Represents a location to which a chat is connected.
	**/
	public static final class ChatLocation extends Object {


		/**
		 * The location.
		**/
		public Location location;

		/**
		 * Location address; 1-64 characters, as defined by the chat owner.
		**/
		public String address;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1566863583;

		/**
		 * Represents a location to which a chat is connected.
		**/
		public ChatLocation() {}

		/**
		 * Represents a location to which a chat is connected.
		 *
		 * @param location The location.
		 * @param address Location address; 1-64 characters, as defined by the chat owner.
		**/
		public ChatLocation(Location location, String address) {
			this.location = location;
			this.address = address;
		}

		/**
		 * Represents a location to which a chat is connected.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatLocation(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Location.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.location = new Location(input);
			}
			if (input.readBoolean()) {
				byte[] addressTmp = new byte[input.readInt()];
				input.readFully(addressTmp);
				this.address = new String(addressTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatLocation.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatLocation.CONSTRUCTOR);
			if (this.location == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.location.serialize(output);
			}
			if (this.address == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] addressTmp = this.address.getBytes(StandardCharsets.UTF_8);
				output.writeInt(addressTmp.length);
				output.write(addressTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatLocation chatLocation = (ChatLocation) o;
			if (!Objects.equals(this.location, chatLocation.location)) {
				return false;
			}
			if (this.address != chatLocation.address) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.location == null ? 0 : this.location.hashCode();
			result = result * 31 + (this.address == null ? 0 : this.address.hashCode());
			return result;
		}
	}

	/**
	 * Describes a user or a chat as a member of another chat.
	**/
	public static final class ChatMember extends Object {


		/**
		 * Identifier of the chat member. Currently, other chats can be only Left or Banned. Only supergroups and channels can have other chats as Left or Banned members and these chats must be supergroups or channels.
		**/
		public MessageSender memberId;

		/**
		 * Identifier of a user that invited/promoted/banned this member in the chat; 0 if unknown.
		**/
		public long inviterUserId;

		/**
		 * Point in time (Unix timestamp) when the user joined/was promoted/was banned in the chat.
		**/
		public int joinedChatDate;

		/**
		 * Status of the member in the chat.
		**/
		public ChatMemberStatus status;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1829953909;

		/**
		 * Describes a user or a chat as a member of another chat.
		**/
		public ChatMember() {}

		/**
		 * Describes a user or a chat as a member of another chat.
		 *
		 * @param memberId Identifier of the chat member. Currently, other chats can be only Left or Banned. Only supergroups and channels can have other chats as Left or Banned members and these chats must be supergroups or channels.
		 * @param inviterUserId Identifier of a user that invited/promoted/banned this member in the chat; 0 if unknown.
		 * @param joinedChatDate Point in time (Unix timestamp) when the user joined/was promoted/was banned in the chat.
		 * @param status Status of the member in the chat.
		**/
		public ChatMember(MessageSender memberId,
				long inviterUserId,
				int joinedChatDate,
				ChatMemberStatus status) {
			this.memberId = memberId;
			this.inviterUserId = inviterUserId;
			this.joinedChatDate = joinedChatDate;
			this.status = status;
		}

		/**
		 * Describes a user or a chat as a member of another chat.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatMember(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case MessageSenderUser.CONSTRUCTOR: this.memberId = new MessageSenderUser(input); break;
					case MessageSenderChat.CONSTRUCTOR: this.memberId = new MessageSenderChat(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.inviterUserId = input.readLong();
			this.joinedChatDate = input.readInt();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ChatMemberStatusCreator.CONSTRUCTOR: this.status = new ChatMemberStatusCreator(input); break;
					case ChatMemberStatusAdministrator.CONSTRUCTOR: this.status = new ChatMemberStatusAdministrator(input); break;
					case ChatMemberStatusMember.CONSTRUCTOR: this.status = new ChatMemberStatusMember(input); break;
					case ChatMemberStatusRestricted.CONSTRUCTOR: this.status = new ChatMemberStatusRestricted(input); break;
					case ChatMemberStatusLeft.CONSTRUCTOR: this.status = new ChatMemberStatusLeft(input); break;
					case ChatMemberStatusBanned.CONSTRUCTOR: this.status = new ChatMemberStatusBanned(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatMember.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatMember.CONSTRUCTOR);
			if (this.memberId == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.memberId.serialize(output);
			}
			output.writeLong(this.inviterUserId);
			output.writeInt(this.joinedChatDate);
			if (this.status == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.status.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatMember chatMember = (ChatMember) o;
			if (!Objects.equals(this.memberId, chatMember.memberId)) {
				return false;
			}
			if (this.inviterUserId != chatMember.inviterUserId) {
				return false;
			}
			if (this.joinedChatDate != chatMember.joinedChatDate) {
				return false;
			}
			if (!Objects.equals(this.status, chatMember.status)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.inviterUserId);
			result = result * 31 + (this.memberId == null ? 0 : this.memberId.hashCode());
			result = result * 31 + (this.status == null ? 0 : this.status.hashCode());
			return result;
		}
	}

	/**
	 * The user is the owner of the chat and has all the administrator
	 * privileges.
	**/
	public static final class ChatMemberStatusCreator extends ChatMemberStatus {


		/**
		 * A custom title of the owner; 0-16 characters without emojis; applicable to supergroups only.
		**/
		public String customTitle;

		/**
		 * True, if the creator isn&#039;t shown in the chat member list and sends messages anonymously; applicable to supergroups only.
		**/
		public boolean isAnonymous;

		/**
		 * True, if the user is a member of the chat.
		**/
		public boolean isMember;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -160019714;

		/**
		 * The user is the owner of the chat and has all the administrator privileges.
		**/
		public ChatMemberStatusCreator() {}

		/**
		 * The user is the owner of the chat and has all the administrator privileges.
		 *
		 * @param customTitle A custom title of the owner; 0-16 characters without emojis; applicable to supergroups only.
		 * @param isAnonymous True, if the creator isn&#039;t shown in the chat member list and sends messages anonymously; applicable to supergroups only.
		 * @param isMember True, if the user is a member of the chat.
		**/
		public ChatMemberStatusCreator(String customTitle, boolean isAnonymous, boolean isMember) {
			this.customTitle = customTitle;
			this.isAnonymous = isAnonymous;
			this.isMember = isMember;
		}

		/**
		 * The user is the owner of the chat and has all the administrator privileges.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatMemberStatusCreator(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] customTitleTmp = new byte[input.readInt()];
				input.readFully(customTitleTmp);
				this.customTitle = new String(customTitleTmp, StandardCharsets.UTF_8);
			}
			this.isAnonymous = input.readBoolean();
			this.isMember = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatMemberStatusCreator.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatMemberStatusCreator.CONSTRUCTOR);
			if (this.customTitle == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] customTitleTmp = this.customTitle.getBytes(StandardCharsets.UTF_8);
				output.writeInt(customTitleTmp.length);
				output.write(customTitleTmp);
			}
			output.writeBoolean(this.isAnonymous);
			output.writeBoolean(this.isMember);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatMemberStatusCreator chatMemberStatusCreator = (ChatMemberStatusCreator) o;
			if (this.customTitle != chatMemberStatusCreator.customTitle) {
				return false;
			}
			if (this.isAnonymous != chatMemberStatusCreator.isAnonymous) {
				return false;
			}
			if (this.isMember != chatMemberStatusCreator.isMember) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isAnonymous);
			result = result * 31 + (this.customTitle == null ? 0 : this.customTitle.hashCode());
			return result;
		}
	}

	/**
	 * The user is a member of the chat and has some additional privileges.
	 * In basic groups, administrators can edit and delete messages sent by
	 * others, add new members, ban unprivileged members, and manage video
	 * chats. In supergroups and channels, there are more detailed options
	 * for administrator privileges.
	**/
	public static final class ChatMemberStatusAdministrator extends ChatMemberStatus {


		/**
		 * A custom title of the administrator; 0-16 characters without emojis; applicable to supergroups only.
		**/
		public String customTitle;

		/**
		 * True, if the current user can edit the administrator privileges for the called user.
		**/
		public boolean canBeEdited;

		/**
		 * Rights of the administrator.
		**/
		public ChatAdministratorRights rights;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -70024163;

		/**
		 * The user is a member of the chat and has some additional privileges. In basic groups, administrators can edit and delete messages sent by others, add new members, ban unprivileged members, and manage video chats. In supergroups and channels, there are more detailed options for administrator privileges.
		**/
		public ChatMemberStatusAdministrator() {}

		/**
		 * The user is a member of the chat and has some additional privileges. In basic groups, administrators can edit and delete messages sent by others, add new members, ban unprivileged members, and manage video chats. In supergroups and channels, there are more detailed options for administrator privileges.
		 *
		 * @param customTitle A custom title of the administrator; 0-16 characters without emojis; applicable to supergroups only.
		 * @param canBeEdited True, if the current user can edit the administrator privileges for the called user.
		 * @param rights Rights of the administrator.
		**/
		public ChatMemberStatusAdministrator(String customTitle,
				boolean canBeEdited,
				ChatAdministratorRights rights) {
			this.customTitle = customTitle;
			this.canBeEdited = canBeEdited;
			this.rights = rights;
		}

		/**
		 * The user is a member of the chat and has some additional privileges. In basic groups, administrators can edit and delete messages sent by others, add new members, ban unprivileged members, and manage video chats. In supergroups and channels, there are more detailed options for administrator privileges.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatMemberStatusAdministrator(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] customTitleTmp = new byte[input.readInt()];
				input.readFully(customTitleTmp);
				this.customTitle = new String(customTitleTmp, StandardCharsets.UTF_8);
			}
			this.canBeEdited = input.readBoolean();
			if (input.readBoolean()) {
				if (ChatAdministratorRights.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.rights = new ChatAdministratorRights(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatMemberStatusAdministrator.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatMemberStatusAdministrator.CONSTRUCTOR);
			if (this.customTitle == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] customTitleTmp = this.customTitle.getBytes(StandardCharsets.UTF_8);
				output.writeInt(customTitleTmp.length);
				output.write(customTitleTmp);
			}
			output.writeBoolean(this.canBeEdited);
			if (this.rights == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.rights.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatMemberStatusAdministrator chatMemberStatusAdministrator = (ChatMemberStatusAdministrator) o;
			if (this.customTitle != chatMemberStatusAdministrator.customTitle) {
				return false;
			}
			if (this.canBeEdited != chatMemberStatusAdministrator.canBeEdited) {
				return false;
			}
			if (!Objects.equals(this.rights, chatMemberStatusAdministrator.rights)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.canBeEdited);
			result = result * 31 + (this.customTitle == null ? 0 : this.customTitle.hashCode());
			result = result * 31 + (this.rights == null ? 0 : this.rights.hashCode());
			return result;
		}
	}

	/**
	 * The user is a member of the chat, without any additional privileges
	 * or restrictions.
	**/
	public static final class ChatMemberStatusMember extends ChatMemberStatus {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 844723285;

		/**
		 * The user is a member of the chat, without any additional privileges or restrictions.
		**/
		public ChatMemberStatusMember() {}

		/**
		 * The user is a member of the chat, without any additional privileges or restrictions.
		 *
		**/

		/**
		 * The user is a member of the chat, without any additional privileges or restrictions.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatMemberStatusMember(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatMemberStatusMember.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatMemberStatusMember.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ChatMemberStatusMember.CONSTRUCTOR;
		}
	}

	/**
	 * The user is under certain restrictions in the chat. Not supported in
	 * basic groups and channels.
	**/
	public static final class ChatMemberStatusRestricted extends ChatMemberStatus {


		/**
		 * True, if the user is a member of the chat.
		**/
		public boolean isMember;

		/**
		 * Point in time (Unix timestamp) when restrictions will be lifted from the user; 0 if never. If the user is restricted for more than 366 days or for less than 30 seconds from the current time, the user is considered to be restricted forever.
		**/
		public int restrictedUntilDate;

		/**
		 * User permissions in the chat.
		**/
		public ChatPermissions permissions;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1661432998;

		/**
		 * The user is under certain restrictions in the chat. Not supported in basic groups and channels.
		**/
		public ChatMemberStatusRestricted() {}

		/**
		 * The user is under certain restrictions in the chat. Not supported in basic groups and channels.
		 *
		 * @param isMember True, if the user is a member of the chat.
		 * @param restrictedUntilDate Point in time (Unix timestamp) when restrictions will be lifted from the user; 0 if never. If the user is restricted for more than 366 days or for less than 30 seconds from the current time, the user is considered to be restricted forever.
		 * @param permissions User permissions in the chat.
		**/
		public ChatMemberStatusRestricted(boolean isMember,
				int restrictedUntilDate,
				ChatPermissions permissions) {
			this.isMember = isMember;
			this.restrictedUntilDate = restrictedUntilDate;
			this.permissions = permissions;
		}

		/**
		 * The user is under certain restrictions in the chat. Not supported in basic groups and channels.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatMemberStatusRestricted(DataInput input) throws IOException {
			this.isMember = input.readBoolean();
			this.restrictedUntilDate = input.readInt();
			if (input.readBoolean()) {
				if (ChatPermissions.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.permissions = new ChatPermissions(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatMemberStatusRestricted.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatMemberStatusRestricted.CONSTRUCTOR);
			output.writeBoolean(this.isMember);
			output.writeInt(this.restrictedUntilDate);
			if (this.permissions == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.permissions.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatMemberStatusRestricted chatMemberStatusRestricted = (ChatMemberStatusRestricted) o;
			if (this.isMember != chatMemberStatusRestricted.isMember) {
				return false;
			}
			if (this.restrictedUntilDate != chatMemberStatusRestricted.restrictedUntilDate) {
				return false;
			}
			if (!Objects.equals(this.permissions, chatMemberStatusRestricted.permissions)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isMember);
			result = result * 31 + (this.permissions == null ? 0 : this.permissions.hashCode());
			return result;
		}
	}

	/**
	 * The user or the chat is not a chat member.
	**/
	public static final class ChatMemberStatusLeft extends ChatMemberStatus {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -5815259;

		/**
		 * The user or the chat is not a chat member.
		**/
		public ChatMemberStatusLeft() {}

		/**
		 * The user or the chat is not a chat member.
		 *
		**/

		/**
		 * The user or the chat is not a chat member.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatMemberStatusLeft(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatMemberStatusLeft.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatMemberStatusLeft.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ChatMemberStatusLeft.CONSTRUCTOR;
		}
	}

	/**
	 * The user or the chat was banned (and hence is not a member of the
	 * chat). Implies the user can&#039;t return to the chat, view messages,
	 * or be used as a participant identifier to join a video chat of the
	 * chat.
	**/
	public static final class ChatMemberStatusBanned extends ChatMemberStatus {


		/**
		 * Point in time (Unix timestamp) when the user will be unbanned; 0 if never. If the user is banned for more than 366 days or for less than 30 seconds from the current time, the user is considered to be banned forever. Always 0 in basic groups.
		**/
		public int bannedUntilDate;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1653518666;

		/**
		 * The user or the chat was banned (and hence is not a member of the chat). Implies the user can&#039;t return to the chat, view messages, or be used as a participant identifier to join a video chat of the chat.
		**/
		public ChatMemberStatusBanned() {}

		/**
		 * The user or the chat was banned (and hence is not a member of the chat). Implies the user can&#039;t return to the chat, view messages, or be used as a participant identifier to join a video chat of the chat.
		 *
		 * @param bannedUntilDate Point in time (Unix timestamp) when the user will be unbanned; 0 if never. If the user is banned for more than 366 days or for less than 30 seconds from the current time, the user is considered to be banned forever. Always 0 in basic groups.
		**/
		public ChatMemberStatusBanned(int bannedUntilDate) {
			this.bannedUntilDate = bannedUntilDate;
		}

		/**
		 * The user or the chat was banned (and hence is not a member of the chat). Implies the user can&#039;t return to the chat, view messages, or be used as a participant identifier to join a video chat of the chat.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatMemberStatusBanned(DataInput input) throws IOException {
			this.bannedUntilDate = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatMemberStatusBanned.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatMemberStatusBanned.CONSTRUCTOR);
			output.writeInt(this.bannedUntilDate);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatMemberStatusBanned chatMemberStatusBanned = (ChatMemberStatusBanned) o;
			if (this.bannedUntilDate != chatMemberStatusBanned.bannedUntilDate) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.bannedUntilDate);
		}
	}

	/**
	 * Contains a list of chat members.
	**/
	public static final class ChatMembers extends Object {


		/**
		 * Approximate total number of chat members found.
		**/
		public int totalCount;

		/**
		 * A list of chat members.
		**/
		public ChatMember[] members;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -497558622;

		/**
		 * Contains a list of chat members.
		**/
		public ChatMembers() {}

		/**
		 * Contains a list of chat members.
		 *
		 * @param totalCount Approximate total number of chat members found.
		 * @param members A list of chat members.
		**/
		public ChatMembers(int totalCount, ChatMember[] members) {
			this.totalCount = totalCount;
			this.members = members;
		}

		/**
		 * Contains a list of chat members.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatMembers(DataInput input) throws IOException {
			this.totalCount = input.readInt();
			if (input.readBoolean()) {
				this.members = new ChatMember[input.readInt()];
				for (int i = 0; i < this.members.length; i++) {
					if (ChatMember.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.members[i] = new ChatMember(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatMembers.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatMembers.CONSTRUCTOR);
			output.writeInt(this.totalCount);
			if (this.members == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.members.length);
				for (int i = 0; i < this.members.length; i++) {
					this.members[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatMembers chatMembers = (ChatMembers) o;
			if (this.totalCount != chatMembers.totalCount) {
				return false;
			}
			if (!Arrays.equals(this.members, chatMembers.members)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.totalCount);
			result = result * 31 + (Arrays.hashCode(this.members));
			return result;
		}
	}

	/**
	 * Returns contacts of the user.
	**/
	public static final class ChatMembersFilterContacts extends ChatMembersFilter {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1774485671;

		/**
		 * Returns contacts of the user.
		**/
		public ChatMembersFilterContacts() {}

		/**
		 * Returns contacts of the user.
		 *
		**/

		/**
		 * Returns contacts of the user.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatMembersFilterContacts(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatMembersFilterContacts.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatMembersFilterContacts.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ChatMembersFilterContacts.CONSTRUCTOR;
		}
	}

	/**
	 * Returns the owner and administrators.
	**/
	public static final class ChatMembersFilterAdministrators extends ChatMembersFilter {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1266893796;

		/**
		 * Returns the owner and administrators.
		**/
		public ChatMembersFilterAdministrators() {}

		/**
		 * Returns the owner and administrators.
		 *
		**/

		/**
		 * Returns the owner and administrators.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatMembersFilterAdministrators(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatMembersFilterAdministrators.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatMembersFilterAdministrators.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ChatMembersFilterAdministrators.CONSTRUCTOR;
		}
	}

	/**
	 * Returns all chat members, including restricted chat members.
	**/
	public static final class ChatMembersFilterMembers extends ChatMembersFilter {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 670504342;

		/**
		 * Returns all chat members, including restricted chat members.
		**/
		public ChatMembersFilterMembers() {}

		/**
		 * Returns all chat members, including restricted chat members.
		 *
		**/

		/**
		 * Returns all chat members, including restricted chat members.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatMembersFilterMembers(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatMembersFilterMembers.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatMembersFilterMembers.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ChatMembersFilterMembers.CONSTRUCTOR;
		}
	}

	/**
	 * Returns users which can be mentioned in the chat.
	**/
	public static final class ChatMembersFilterMention extends ChatMembersFilter {


		/**
		 * If non-zero, the identifier of the current message thread.
		**/
		public long messageThreadId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 856419831;

		/**
		 * Returns users which can be mentioned in the chat.
		**/
		public ChatMembersFilterMention() {}

		/**
		 * Returns users which can be mentioned in the chat.
		 *
		 * @param messageThreadId If non-zero, the identifier of the current message thread.
		**/
		public ChatMembersFilterMention(long messageThreadId) {
			this.messageThreadId = messageThreadId;
		}

		/**
		 * Returns users which can be mentioned in the chat.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatMembersFilterMention(DataInput input) throws IOException {
			this.messageThreadId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatMembersFilterMention.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatMembersFilterMention.CONSTRUCTOR);
			output.writeLong(this.messageThreadId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatMembersFilterMention chatMembersFilterMention = (ChatMembersFilterMention) o;
			if (this.messageThreadId != chatMembersFilterMention.messageThreadId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.messageThreadId);
		}
	}

	/**
	 * Returns users under certain restrictions in the chat; can be used
	 * only by administrators in a supergroup.
	**/
	public static final class ChatMembersFilterRestricted extends ChatMembersFilter {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1256282813;

		/**
		 * Returns users under certain restrictions in the chat; can be used only by administrators in a supergroup.
		**/
		public ChatMembersFilterRestricted() {}

		/**
		 * Returns users under certain restrictions in the chat; can be used only by administrators in a supergroup.
		 *
		**/

		/**
		 * Returns users under certain restrictions in the chat; can be used only by administrators in a supergroup.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatMembersFilterRestricted(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatMembersFilterRestricted.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatMembersFilterRestricted.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ChatMembersFilterRestricted.CONSTRUCTOR;
		}
	}

	/**
	 * Returns users banned from the chat; can be used only by
	 * administrators in a supergroup or in a channel.
	**/
	public static final class ChatMembersFilterBanned extends ChatMembersFilter {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1863102648;

		/**
		 * Returns users banned from the chat; can be used only by administrators in a supergroup or in a channel.
		**/
		public ChatMembersFilterBanned() {}

		/**
		 * Returns users banned from the chat; can be used only by administrators in a supergroup or in a channel.
		 *
		**/

		/**
		 * Returns users banned from the chat; can be used only by administrators in a supergroup or in a channel.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatMembersFilterBanned(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatMembersFilterBanned.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatMembersFilterBanned.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ChatMembersFilterBanned.CONSTRUCTOR;
		}
	}

	/**
	 * Returns bot members of the chat.
	**/
	public static final class ChatMembersFilterBots extends ChatMembersFilter {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1422567288;

		/**
		 * Returns bot members of the chat.
		**/
		public ChatMembersFilterBots() {}

		/**
		 * Returns bot members of the chat.
		 *
		**/

		/**
		 * Returns bot members of the chat.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatMembersFilterBots(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatMembersFilterBots.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatMembersFilterBots.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ChatMembersFilterBots.CONSTRUCTOR;
		}
	}

	/**
	 * Represents a message sender, which can be used to send messages in a
	 * chat.
	**/
	public static final class ChatMessageSender extends Object {


		/**
		 * Available message senders.
		**/
		public MessageSender sender;

		/**
		 * True, if Telegram Premium is needed to use the message sender.
		**/
		public boolean needsPremium;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 760590010;

		/**
		 * Represents a message sender, which can be used to send messages in a chat.
		**/
		public ChatMessageSender() {}

		/**
		 * Represents a message sender, which can be used to send messages in a chat.
		 *
		 * @param sender Available message senders.
		 * @param needsPremium True, if Telegram Premium is needed to use the message sender.
		**/
		public ChatMessageSender(MessageSender sender, boolean needsPremium) {
			this.sender = sender;
			this.needsPremium = needsPremium;
		}

		/**
		 * Represents a message sender, which can be used to send messages in a chat.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatMessageSender(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case MessageSenderUser.CONSTRUCTOR: this.sender = new MessageSenderUser(input); break;
					case MessageSenderChat.CONSTRUCTOR: this.sender = new MessageSenderChat(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.needsPremium = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatMessageSender.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatMessageSender.CONSTRUCTOR);
			if (this.sender == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.sender.serialize(output);
			}
			output.writeBoolean(this.needsPremium);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatMessageSender chatMessageSender = (ChatMessageSender) o;
			if (!Objects.equals(this.sender, chatMessageSender.sender)) {
				return false;
			}
			if (this.needsPremium != chatMessageSender.needsPremium) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.needsPremium);
			result = result * 31 + (this.sender == null ? 0 : this.sender.hashCode());
			return result;
		}
	}

	/**
	 * Represents a list of message senders, which can be used to send
	 * messages in a chat.
	**/
	public static final class ChatMessageSenders extends Object {


		/**
		 * List of available message senders.
		**/
		public ChatMessageSender[] senders;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1866230970;

		/**
		 * Represents a list of message senders, which can be used to send messages in a chat.
		**/
		public ChatMessageSenders() {}

		/**
		 * Represents a list of message senders, which can be used to send messages in a chat.
		 *
		 * @param senders List of available message senders.
		**/
		public ChatMessageSenders(ChatMessageSender[] senders) {
			this.senders = senders;
		}

		/**
		 * Represents a list of message senders, which can be used to send messages in a chat.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatMessageSenders(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.senders = new ChatMessageSender[input.readInt()];
				for (int i = 0; i < this.senders.length; i++) {
					if (ChatMessageSender.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.senders[i] = new ChatMessageSender(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatMessageSenders.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatMessageSenders.CONSTRUCTOR);
			if (this.senders == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.senders.length);
				for (int i = 0; i < this.senders.length; i++) {
					this.senders[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatMessageSenders chatMessageSenders = (ChatMessageSenders) o;
			if (!Arrays.equals(this.senders, chatMessageSenders.senders)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.senders);
		}
	}

	/**
	 * Describes a chat located nearby.
	**/
	public static final class ChatNearby extends Object {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Distance to the chat location, in meters.
		**/
		public int distance;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 48120405;

		/**
		 * Describes a chat located nearby.
		**/
		public ChatNearby() {}

		/**
		 * Describes a chat located nearby.
		 *
		 * @param chatId Chat identifier.
		 * @param distance Distance to the chat location, in meters.
		**/
		public ChatNearby(long chatId, int distance) {
			this.chatId = chatId;
			this.distance = distance;
		}

		/**
		 * Describes a chat located nearby.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatNearby(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.distance = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatNearby.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatNearby.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeInt(this.distance);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatNearby chatNearby = (ChatNearby) o;
			if (this.chatId != chatNearby.chatId) {
				return false;
			}
			if (this.distance != chatNearby.distance) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Contains information about notification settings for a chat or a
	 * forum topic.
	**/
	public static final class ChatNotificationSettings extends Object {


		/**
		 * If true, muteFor is ignored and the value for the relevant type of chat or the forum chat is used instead.
		**/
		public boolean useDefaultMuteFor;

		/**
		 * Time left before notifications will be unmuted, in seconds.
		**/
		public int muteFor;

		/**
		 * If true, the value for the relevant type of chat or the forum chat is used instead of soundId.
		**/
		public boolean useDefaultSound;

		/**
		 * Identifier of the notification sound to be played; 0 if sound is disabled.
		**/
		public long soundId;

		/**
		 * If true, showPreview is ignored and the value for the relevant type of chat or the forum chat is used instead.
		**/
		public boolean useDefaultShowPreview;

		/**
		 * True, if message content must be displayed in notifications.
		**/
		public boolean showPreview;

		/**
		 * If true, disablePinnedMessageNotifications is ignored and the value for the relevant type of chat or the forum chat is used instead.
		**/
		public boolean useDefaultDisablePinnedMessageNotifications;

		/**
		 * If true, notifications for incoming pinned messages will be created as for an ordinary unread message.
		**/
		public boolean disablePinnedMessageNotifications;

		/**
		 * If true, disableMentionNotifications is ignored and the value for the relevant type of chat or the forum chat is used instead.
		**/
		public boolean useDefaultDisableMentionNotifications;

		/**
		 * If true, notifications for messages with mentions will be created as for an ordinary unread message.
		**/
		public boolean disableMentionNotifications;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 944322400;

		/**
		 * Contains information about notification settings for a chat or a forum topic.
		**/
		public ChatNotificationSettings() {}

		/**
		 * Contains information about notification settings for a chat or a forum topic.
		 *
		 * @param useDefaultMuteFor If true, muteFor is ignored and the value for the relevant type of chat or the forum chat is used instead.
		 * @param muteFor Time left before notifications will be unmuted, in seconds.
		 * @param useDefaultSound If true, the value for the relevant type of chat or the forum chat is used instead of soundId.
		 * @param soundId Identifier of the notification sound to be played; 0 if sound is disabled.
		 * @param useDefaultShowPreview If true, showPreview is ignored and the value for the relevant type of chat or the forum chat is used instead.
		 * @param showPreview True, if message content must be displayed in notifications.
		 * @param useDefaultDisablePinnedMessageNotifications If true, disablePinnedMessageNotifications is ignored and the value for the relevant type of chat or the forum chat is used instead.
		 * @param disablePinnedMessageNotifications If true, notifications for incoming pinned messages will be created as for an ordinary unread message.
		 * @param useDefaultDisableMentionNotifications If true, disableMentionNotifications is ignored and the value for the relevant type of chat or the forum chat is used instead.
		 * @param disableMentionNotifications If true, notifications for messages with mentions will be created as for an ordinary unread message.
		**/
		public ChatNotificationSettings(boolean useDefaultMuteFor,
				int muteFor,
				boolean useDefaultSound,
				long soundId,
				boolean useDefaultShowPreview,
				boolean showPreview,
				boolean useDefaultDisablePinnedMessageNotifications,
				boolean disablePinnedMessageNotifications,
				boolean useDefaultDisableMentionNotifications,
				boolean disableMentionNotifications) {
			this.useDefaultMuteFor = useDefaultMuteFor;
			this.muteFor = muteFor;
			this.useDefaultSound = useDefaultSound;
			this.soundId = soundId;
			this.useDefaultShowPreview = useDefaultShowPreview;
			this.showPreview = showPreview;
			this.useDefaultDisablePinnedMessageNotifications = useDefaultDisablePinnedMessageNotifications;
			this.disablePinnedMessageNotifications = disablePinnedMessageNotifications;
			this.useDefaultDisableMentionNotifications = useDefaultDisableMentionNotifications;
			this.disableMentionNotifications = disableMentionNotifications;
		}

		/**
		 * Contains information about notification settings for a chat or a forum topic.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatNotificationSettings(DataInput input) throws IOException {
			this.useDefaultMuteFor = input.readBoolean();
			this.muteFor = input.readInt();
			this.useDefaultSound = input.readBoolean();
			this.soundId = input.readLong();
			this.useDefaultShowPreview = input.readBoolean();
			this.showPreview = input.readBoolean();
			this.useDefaultDisablePinnedMessageNotifications = input.readBoolean();
			this.disablePinnedMessageNotifications = input.readBoolean();
			this.useDefaultDisableMentionNotifications = input.readBoolean();
			this.disableMentionNotifications = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatNotificationSettings.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatNotificationSettings.CONSTRUCTOR);
			output.writeBoolean(this.useDefaultMuteFor);
			output.writeInt(this.muteFor);
			output.writeBoolean(this.useDefaultSound);
			output.writeLong(this.soundId);
			output.writeBoolean(this.useDefaultShowPreview);
			output.writeBoolean(this.showPreview);
			output.writeBoolean(this.useDefaultDisablePinnedMessageNotifications);
			output.writeBoolean(this.disablePinnedMessageNotifications);
			output.writeBoolean(this.useDefaultDisableMentionNotifications);
			output.writeBoolean(this.disableMentionNotifications);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatNotificationSettings chatNotificationSettings = (ChatNotificationSettings) o;
			if (this.useDefaultMuteFor != chatNotificationSettings.useDefaultMuteFor) {
				return false;
			}
			if (this.muteFor != chatNotificationSettings.muteFor) {
				return false;
			}
			if (this.useDefaultSound != chatNotificationSettings.useDefaultSound) {
				return false;
			}
			if (this.soundId != chatNotificationSettings.soundId) {
				return false;
			}
			if (this.useDefaultShowPreview != chatNotificationSettings.useDefaultShowPreview) {
				return false;
			}
			if (this.showPreview != chatNotificationSettings.showPreview) {
				return false;
			}
			if (this.useDefaultDisablePinnedMessageNotifications != chatNotificationSettings.useDefaultDisablePinnedMessageNotifications) {
				return false;
			}
			if (this.disablePinnedMessageNotifications != chatNotificationSettings.disablePinnedMessageNotifications) {
				return false;
			}
			if (this.useDefaultDisableMentionNotifications != chatNotificationSettings.useDefaultDisableMentionNotifications) {
				return false;
			}
			if (this.disableMentionNotifications != chatNotificationSettings.disableMentionNotifications) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.useDefaultMuteFor);
			return result;
		}
	}

	/**
	 * Describes actions that a user is allowed to take in a chat.
	**/
	public static final class ChatPermissions extends Object {


		/**
		 * True, if the user can send text messages, contacts, invoices, locations, and venues.
		**/
		public boolean canSendBasicMessages;

		/**
		 * True, if the user can send music files.
		**/
		public boolean canSendAudios;

		/**
		 * True, if the user can send documents.
		**/
		public boolean canSendDocuments;

		/**
		 * True, if the user can send audio photos.
		**/
		public boolean canSendPhotos;

		/**
		 * True, if the user can send audio videos.
		**/
		public boolean canSendVideos;

		/**
		 * True, if the user can send video notes.
		**/
		public boolean canSendVideoNotes;

		/**
		 * True, if the user can send voice notes.
		**/
		public boolean canSendVoiceNotes;

		/**
		 * True, if the user can send polls.
		**/
		public boolean canSendPolls;

		/**
		 * True, if the user can send animations, games, stickers, and dice and use inline bots.
		**/
		public boolean canSendOtherMessages;

		/**
		 * True, if the user may add a web page preview to their messages.
		**/
		public boolean canAddWebPagePreviews;

		/**
		 * True, if the user can change the chat title, photo, and other settings.
		**/
		public boolean canChangeInfo;

		/**
		 * True, if the user can invite new users to the chat.
		**/
		public boolean canInviteUsers;

		/**
		 * True, if the user can pin messages.
		**/
		public boolean canPinMessages;

		/**
		 * True, if the user can manage topics.
		**/
		public boolean canManageTopics;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1355062837;

		/**
		 * Describes actions that a user is allowed to take in a chat.
		**/
		public ChatPermissions() {}

		/**
		 * Describes actions that a user is allowed to take in a chat.
		 *
		 * @param canSendBasicMessages True, if the user can send text messages, contacts, invoices, locations, and venues.
		 * @param canSendAudios True, if the user can send music files.
		 * @param canSendDocuments True, if the user can send documents.
		 * @param canSendPhotos True, if the user can send audio photos.
		 * @param canSendVideos True, if the user can send audio videos.
		 * @param canSendVideoNotes True, if the user can send video notes.
		 * @param canSendVoiceNotes True, if the user can send voice notes.
		 * @param canSendPolls True, if the user can send polls.
		 * @param canSendOtherMessages True, if the user can send animations, games, stickers, and dice and use inline bots.
		 * @param canAddWebPagePreviews True, if the user may add a web page preview to their messages.
		 * @param canChangeInfo True, if the user can change the chat title, photo, and other settings.
		 * @param canInviteUsers True, if the user can invite new users to the chat.
		 * @param canPinMessages True, if the user can pin messages.
		 * @param canManageTopics True, if the user can manage topics.
		**/
		public ChatPermissions(boolean canSendBasicMessages,
				boolean canSendAudios,
				boolean canSendDocuments,
				boolean canSendPhotos,
				boolean canSendVideos,
				boolean canSendVideoNotes,
				boolean canSendVoiceNotes,
				boolean canSendPolls,
				boolean canSendOtherMessages,
				boolean canAddWebPagePreviews,
				boolean canChangeInfo,
				boolean canInviteUsers,
				boolean canPinMessages,
				boolean canManageTopics) {
			this.canSendBasicMessages = canSendBasicMessages;
			this.canSendAudios = canSendAudios;
			this.canSendDocuments = canSendDocuments;
			this.canSendPhotos = canSendPhotos;
			this.canSendVideos = canSendVideos;
			this.canSendVideoNotes = canSendVideoNotes;
			this.canSendVoiceNotes = canSendVoiceNotes;
			this.canSendPolls = canSendPolls;
			this.canSendOtherMessages = canSendOtherMessages;
			this.canAddWebPagePreviews = canAddWebPagePreviews;
			this.canChangeInfo = canChangeInfo;
			this.canInviteUsers = canInviteUsers;
			this.canPinMessages = canPinMessages;
			this.canManageTopics = canManageTopics;
		}

		/**
		 * Describes actions that a user is allowed to take in a chat.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatPermissions(DataInput input) throws IOException {
			this.canSendBasicMessages = input.readBoolean();
			this.canSendAudios = input.readBoolean();
			this.canSendDocuments = input.readBoolean();
			this.canSendPhotos = input.readBoolean();
			this.canSendVideos = input.readBoolean();
			this.canSendVideoNotes = input.readBoolean();
			this.canSendVoiceNotes = input.readBoolean();
			this.canSendPolls = input.readBoolean();
			this.canSendOtherMessages = input.readBoolean();
			this.canAddWebPagePreviews = input.readBoolean();
			this.canChangeInfo = input.readBoolean();
			this.canInviteUsers = input.readBoolean();
			this.canPinMessages = input.readBoolean();
			this.canManageTopics = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatPermissions.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatPermissions.CONSTRUCTOR);
			output.writeBoolean(this.canSendBasicMessages);
			output.writeBoolean(this.canSendAudios);
			output.writeBoolean(this.canSendDocuments);
			output.writeBoolean(this.canSendPhotos);
			output.writeBoolean(this.canSendVideos);
			output.writeBoolean(this.canSendVideoNotes);
			output.writeBoolean(this.canSendVoiceNotes);
			output.writeBoolean(this.canSendPolls);
			output.writeBoolean(this.canSendOtherMessages);
			output.writeBoolean(this.canAddWebPagePreviews);
			output.writeBoolean(this.canChangeInfo);
			output.writeBoolean(this.canInviteUsers);
			output.writeBoolean(this.canPinMessages);
			output.writeBoolean(this.canManageTopics);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatPermissions chatPermissions = (ChatPermissions) o;
			if (this.canSendBasicMessages != chatPermissions.canSendBasicMessages) {
				return false;
			}
			if (this.canSendAudios != chatPermissions.canSendAudios) {
				return false;
			}
			if (this.canSendDocuments != chatPermissions.canSendDocuments) {
				return false;
			}
			if (this.canSendPhotos != chatPermissions.canSendPhotos) {
				return false;
			}
			if (this.canSendVideos != chatPermissions.canSendVideos) {
				return false;
			}
			if (this.canSendVideoNotes != chatPermissions.canSendVideoNotes) {
				return false;
			}
			if (this.canSendVoiceNotes != chatPermissions.canSendVoiceNotes) {
				return false;
			}
			if (this.canSendPolls != chatPermissions.canSendPolls) {
				return false;
			}
			if (this.canSendOtherMessages != chatPermissions.canSendOtherMessages) {
				return false;
			}
			if (this.canAddWebPagePreviews != chatPermissions.canAddWebPagePreviews) {
				return false;
			}
			if (this.canChangeInfo != chatPermissions.canChangeInfo) {
				return false;
			}
			if (this.canInviteUsers != chatPermissions.canInviteUsers) {
				return false;
			}
			if (this.canPinMessages != chatPermissions.canPinMessages) {
				return false;
			}
			if (this.canManageTopics != chatPermissions.canManageTopics) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.canSendBasicMessages);
			return result;
		}
	}

	/**
	 * Describes a chat or user profile photo.
	**/
	public static final class ChatPhoto extends Object {


		/**
		 * Unique photo identifier.
		**/
		public long id;

		/**
		 * Point in time (Unix timestamp) when the photo has been added.
		**/
		public int addedDate;

		/**
		 * Photo minithumbnail; may be null.
		**/
		public Minithumbnail minithumbnail;

		/**
		 * Available variants of the photo in JPEG format, in different size.
		**/
		public PhotoSize[] sizes;

		/**
		 * A big (up to 1280x1280) animated variant of the photo in MPEG4 format; may be null.
		**/
		public AnimatedChatPhoto animation;

		/**
		 * A small (160x160) animated variant of the photo in MPEG4 format; may be null even the big animation is available.
		**/
		public AnimatedChatPhoto smallAnimation;

		/**
		 * Sticker-based version of the chat photo; may be null.
		**/
		public ChatPhotoSticker sticker;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1430870201;

		/**
		 * Describes a chat or user profile photo.
		**/
		public ChatPhoto() {}

		/**
		 * Describes a chat or user profile photo.
		 *
		 * @param id Unique photo identifier.
		 * @param addedDate Point in time (Unix timestamp) when the photo has been added.
		 * @param minithumbnail Photo minithumbnail; may be null.
		 * @param sizes Available variants of the photo in JPEG format, in different size.
		 * @param animation A big (up to 1280x1280) animated variant of the photo in MPEG4 format; may be null.
		 * @param smallAnimation A small (160x160) animated variant of the photo in MPEG4 format; may be null even the big animation is available.
		 * @param sticker Sticker-based version of the chat photo; may be null.
		**/
		public ChatPhoto(long id,
				int addedDate,
				Minithumbnail minithumbnail,
				PhotoSize[] sizes,
				AnimatedChatPhoto animation,
				AnimatedChatPhoto smallAnimation,
				ChatPhotoSticker sticker) {
			this.id = id;
			this.addedDate = addedDate;
			this.minithumbnail = minithumbnail;
			this.sizes = sizes;
			this.animation = animation;
			this.smallAnimation = smallAnimation;
			this.sticker = sticker;
		}

		/**
		 * Describes a chat or user profile photo.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatPhoto(DataInput input) throws IOException {
			this.id = input.readLong();
			this.addedDate = input.readInt();
			if (input.readBoolean()) {
				if (Minithumbnail.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.minithumbnail = new Minithumbnail(input);
			}
			if (input.readBoolean()) {
				this.sizes = new PhotoSize[input.readInt()];
				for (int i = 0; i < this.sizes.length; i++) {
					if (PhotoSize.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.sizes[i] = new PhotoSize(input);
				}
			}
			if (input.readBoolean()) {
				if (AnimatedChatPhoto.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.animation = new AnimatedChatPhoto(input);
			}
			if (input.readBoolean()) {
				if (AnimatedChatPhoto.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.smallAnimation = new AnimatedChatPhoto(input);
			}
			if (input.readBoolean()) {
				if (ChatPhotoSticker.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.sticker = new ChatPhotoSticker(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatPhoto.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatPhoto.CONSTRUCTOR);
			output.writeLong(this.id);
			output.writeInt(this.addedDate);
			if (this.minithumbnail == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.minithumbnail.serialize(output);
			}
			if (this.sizes == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.sizes.length);
				for (int i = 0; i < this.sizes.length; i++) {
					this.sizes[i].serialize(output);
				}
			}
			if (this.animation == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.animation.serialize(output);
			}
			if (this.smallAnimation == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.smallAnimation.serialize(output);
			}
			if (this.sticker == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.sticker.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatPhoto chatPhoto = (ChatPhoto) o;
			if (this.id != chatPhoto.id) {
				return false;
			}
			if (this.addedDate != chatPhoto.addedDate) {
				return false;
			}
			if (!Objects.equals(this.minithumbnail, chatPhoto.minithumbnail)) {
				return false;
			}
			if (!Arrays.equals(this.sizes, chatPhoto.sizes)) {
				return false;
			}
			if (!Objects.equals(this.animation, chatPhoto.animation)) {
				return false;
			}
			if (!Objects.equals(this.smallAnimation, chatPhoto.smallAnimation)) {
				return false;
			}
			if (!Objects.equals(this.sticker, chatPhoto.sticker)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.id);
			result = result * 31 + (this.minithumbnail == null ? 0 : this.minithumbnail.hashCode());
			result = result * 31 + (Arrays.hashCode(this.sizes));
			result = result * 31 + (this.animation == null ? 0 : this.animation.hashCode());
			result = result * 31 + (this.smallAnimation == null ? 0 : this.smallAnimation.hashCode());
			result = result * 31 + (this.sticker == null ? 0 : this.sticker.hashCode());
			return result;
		}
	}

	/**
	 * Contains basic information about the photo of a chat.
	**/
	public static final class ChatPhotoInfo extends Object {


		/**
		 * A small (160x160) chat photo variant in JPEG format. The file can be downloaded only before the photo is changed.
		**/
		public File small;

		/**
		 * A big (640x640) chat photo variant in JPEG format. The file can be downloaded only before the photo is changed.
		**/
		public File big;

		/**
		 * Chat photo minithumbnail; may be null.
		**/
		public Minithumbnail minithumbnail;

		/**
		 * True, if the photo has animated variant.
		**/
		public boolean hasAnimation;

		/**
		 * True, if the photo is visible only for the current user.
		**/
		public boolean isPersonal;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 281195686;

		/**
		 * Contains basic information about the photo of a chat.
		**/
		public ChatPhotoInfo() {}

		/**
		 * Contains basic information about the photo of a chat.
		 *
		 * @param small A small (160x160) chat photo variant in JPEG format. The file can be downloaded only before the photo is changed.
		 * @param big A big (640x640) chat photo variant in JPEG format. The file can be downloaded only before the photo is changed.
		 * @param minithumbnail Chat photo minithumbnail; may be null.
		 * @param hasAnimation True, if the photo has animated variant.
		 * @param isPersonal True, if the photo is visible only for the current user.
		**/
		public ChatPhotoInfo(File small,
				File big,
				Minithumbnail minithumbnail,
				boolean hasAnimation,
				boolean isPersonal) {
			this.small = small;
			this.big = big;
			this.minithumbnail = minithumbnail;
			this.hasAnimation = hasAnimation;
			this.isPersonal = isPersonal;
		}

		/**
		 * Contains basic information about the photo of a chat.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatPhotoInfo(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (File.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.small = new File(input);
			}
			if (input.readBoolean()) {
				if (File.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.big = new File(input);
			}
			if (input.readBoolean()) {
				if (Minithumbnail.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.minithumbnail = new Minithumbnail(input);
			}
			this.hasAnimation = input.readBoolean();
			this.isPersonal = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatPhotoInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatPhotoInfo.CONSTRUCTOR);
			if (this.small == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.small.serialize(output);
			}
			if (this.big == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.big.serialize(output);
			}
			if (this.minithumbnail == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.minithumbnail.serialize(output);
			}
			output.writeBoolean(this.hasAnimation);
			output.writeBoolean(this.isPersonal);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatPhotoInfo chatPhotoInfo = (ChatPhotoInfo) o;
			if (!Objects.equals(this.small, chatPhotoInfo.small)) {
				return false;
			}
			if (!Objects.equals(this.big, chatPhotoInfo.big)) {
				return false;
			}
			if (!Objects.equals(this.minithumbnail, chatPhotoInfo.minithumbnail)) {
				return false;
			}
			if (this.hasAnimation != chatPhotoInfo.hasAnimation) {
				return false;
			}
			if (this.isPersonal != chatPhotoInfo.isPersonal) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.hasAnimation);
			result = result * 31 + (this.small == null ? 0 : this.small.hashCode());
			result = result * 31 + (this.big == null ? 0 : this.big.hashCode());
			result = result * 31 + (this.minithumbnail == null ? 0 : this.minithumbnail.hashCode());
			return result;
		}
	}

	/**
	 * Information about the sticker, which was used to create the chat
	 * photo. The sticker is shown at the center of the photo and occupies
	 * at most 67% of it.
	**/
	public static final class ChatPhotoSticker extends Object {


		/**
		 * Type of the sticker.
		**/
		public ChatPhotoStickerType type;

		/**
		 * The fill to be used as background for the sticker; rotation angle in backgroundFillGradient isn&#039;t supported.
		**/
		public BackgroundFill backgroundFill;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1459387485;

		/**
		 * Information about the sticker, which was used to create the chat photo. The sticker is shown at the center of the photo and occupies at most 67% of it.
		**/
		public ChatPhotoSticker() {}

		/**
		 * Information about the sticker, which was used to create the chat photo. The sticker is shown at the center of the photo and occupies at most 67% of it.
		 *
		 * @param type Type of the sticker.
		 * @param backgroundFill The fill to be used as background for the sticker; rotation angle in backgroundFillGradient isn&#039;t supported.
		**/
		public ChatPhotoSticker(ChatPhotoStickerType type, BackgroundFill backgroundFill) {
			this.type = type;
			this.backgroundFill = backgroundFill;
		}

		/**
		 * Information about the sticker, which was used to create the chat photo. The sticker is shown at the center of the photo and occupies at most 67% of it.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatPhotoSticker(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ChatPhotoStickerTypeRegularOrMask.CONSTRUCTOR: this.type = new ChatPhotoStickerTypeRegularOrMask(input); break;
					case ChatPhotoStickerTypeCustomEmoji.CONSTRUCTOR: this.type = new ChatPhotoStickerTypeCustomEmoji(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case BackgroundFillSolid.CONSTRUCTOR: this.backgroundFill = new BackgroundFillSolid(input); break;
					case BackgroundFillGradient.CONSTRUCTOR: this.backgroundFill = new BackgroundFillGradient(input); break;
					case BackgroundFillFreeformGradient.CONSTRUCTOR: this.backgroundFill = new BackgroundFillFreeformGradient(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatPhotoSticker.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatPhotoSticker.CONSTRUCTOR);
			if (this.type == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.type.serialize(output);
			}
			if (this.backgroundFill == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.backgroundFill.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatPhotoSticker chatPhotoSticker = (ChatPhotoSticker) o;
			if (!Objects.equals(this.type, chatPhotoSticker.type)) {
				return false;
			}
			if (!Objects.equals(this.backgroundFill, chatPhotoSticker.backgroundFill)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.type == null ? 0 : this.type.hashCode();
			result = result * 31 + (this.backgroundFill == null ? 0 : this.backgroundFill.hashCode());
			return result;
		}
	}

	/**
	 * Information about the sticker, which was used to create the chat
	 * photo.
	**/
	public static final class ChatPhotoStickerTypeRegularOrMask extends ChatPhotoStickerType {


		/**
		 * Sticker set identifier.
		**/
		public long stickerSetId;

		/**
		 * Identifier of the sticker in the set.
		**/
		public long stickerId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -415147620;

		/**
		 * Information about the sticker, which was used to create the chat photo.
		**/
		public ChatPhotoStickerTypeRegularOrMask() {}

		/**
		 * Information about the sticker, which was used to create the chat photo.
		 *
		 * @param stickerSetId Sticker set identifier.
		 * @param stickerId Identifier of the sticker in the set.
		**/
		public ChatPhotoStickerTypeRegularOrMask(long stickerSetId, long stickerId) {
			this.stickerSetId = stickerSetId;
			this.stickerId = stickerId;
		}

		/**
		 * Information about the sticker, which was used to create the chat photo.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatPhotoStickerTypeRegularOrMask(DataInput input) throws IOException {
			this.stickerSetId = input.readLong();
			this.stickerId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatPhotoStickerTypeRegularOrMask.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatPhotoStickerTypeRegularOrMask.CONSTRUCTOR);
			output.writeLong(this.stickerSetId);
			output.writeLong(this.stickerId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatPhotoStickerTypeRegularOrMask chatPhotoStickerTypeRegularOrMask = (ChatPhotoStickerTypeRegularOrMask) o;
			if (this.stickerSetId != chatPhotoStickerTypeRegularOrMask.stickerSetId) {
				return false;
			}
			if (this.stickerId != chatPhotoStickerTypeRegularOrMask.stickerId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.stickerSetId);
			return result;
		}
	}

	/**
	 * Information about the custom emoji, which was used to create the chat
	 * photo.
	**/
	public static final class ChatPhotoStickerTypeCustomEmoji extends ChatPhotoStickerType {


		/**
		 * Identifier of the custom emoji.
		**/
		public long customEmojiId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -266224943;

		/**
		 * Information about the custom emoji, which was used to create the chat photo.
		**/
		public ChatPhotoStickerTypeCustomEmoji() {}

		/**
		 * Information about the custom emoji, which was used to create the chat photo.
		 *
		 * @param customEmojiId Identifier of the custom emoji.
		**/
		public ChatPhotoStickerTypeCustomEmoji(long customEmojiId) {
			this.customEmojiId = customEmojiId;
		}

		/**
		 * Information about the custom emoji, which was used to create the chat photo.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatPhotoStickerTypeCustomEmoji(DataInput input) throws IOException {
			this.customEmojiId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatPhotoStickerTypeCustomEmoji.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatPhotoStickerTypeCustomEmoji.CONSTRUCTOR);
			output.writeLong(this.customEmojiId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatPhotoStickerTypeCustomEmoji chatPhotoStickerTypeCustomEmoji = (ChatPhotoStickerTypeCustomEmoji) o;
			if (this.customEmojiId != chatPhotoStickerTypeCustomEmoji.customEmojiId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.customEmojiId);
		}
	}

	/**
	 * Contains a list of chat or user profile photos.
	**/
	public static final class ChatPhotos extends Object {


		/**
		 * Total number of photos.
		**/
		public int totalCount;

		/**
		 * List of photos.
		**/
		public ChatPhoto[] photos;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1510699180;

		/**
		 * Contains a list of chat or user profile photos.
		**/
		public ChatPhotos() {}

		/**
		 * Contains a list of chat or user profile photos.
		 *
		 * @param totalCount Total number of photos.
		 * @param photos List of photos.
		**/
		public ChatPhotos(int totalCount, ChatPhoto[] photos) {
			this.totalCount = totalCount;
			this.photos = photos;
		}

		/**
		 * Contains a list of chat or user profile photos.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatPhotos(DataInput input) throws IOException {
			this.totalCount = input.readInt();
			if (input.readBoolean()) {
				this.photos = new ChatPhoto[input.readInt()];
				for (int i = 0; i < this.photos.length; i++) {
					if (ChatPhoto.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.photos[i] = new ChatPhoto(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatPhotos.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatPhotos.CONSTRUCTOR);
			output.writeInt(this.totalCount);
			if (this.photos == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.photos.length);
				for (int i = 0; i < this.photos.length; i++) {
					this.photos[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatPhotos chatPhotos = (ChatPhotos) o;
			if (this.totalCount != chatPhotos.totalCount) {
				return false;
			}
			if (!Arrays.equals(this.photos, chatPhotos.photos)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.totalCount);
			result = result * 31 + (Arrays.hashCode(this.photos));
			return result;
		}
	}

	/**
	 * Describes a position of a chat in a chat list.
	**/
	public static final class ChatPosition extends Object {


		/**
		 * The chat list.
		**/
		public ChatList list;

		/**
		 * A parameter used to determine order of the chat in the chat list. Chats must be sorted by the pair (order, chat.id) in descending order.
		**/
		public long order;

		/**
		 * True, if the chat is pinned in the chat list.
		**/
		public boolean isPinned;

		/**
		 * Source of the chat in the chat list; may be null.
		**/
		public ChatSource source;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -622557355;

		/**
		 * Describes a position of a chat in a chat list.
		**/
		public ChatPosition() {}

		/**
		 * Describes a position of a chat in a chat list.
		 *
		 * @param list The chat list.
		 * @param order A parameter used to determine order of the chat in the chat list. Chats must be sorted by the pair (order, chat.id) in descending order.
		 * @param isPinned True, if the chat is pinned in the chat list.
		 * @param source Source of the chat in the chat list; may be null.
		**/
		public ChatPosition(ChatList list,
				long order,
				boolean isPinned,
				ChatSource source) {
			this.list = list;
			this.order = order;
			this.isPinned = isPinned;
			this.source = source;
		}

		/**
		 * Describes a position of a chat in a chat list.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatPosition(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ChatListMain.CONSTRUCTOR: this.list = new ChatListMain(input); break;
					case ChatListArchive.CONSTRUCTOR: this.list = new ChatListArchive(input); break;
					case ChatListFolder.CONSTRUCTOR: this.list = new ChatListFolder(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.order = input.readLong();
			this.isPinned = input.readBoolean();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ChatSourceMtprotoProxy.CONSTRUCTOR: this.source = new ChatSourceMtprotoProxy(input); break;
					case ChatSourcePublicServiceAnnouncement.CONSTRUCTOR: this.source = new ChatSourcePublicServiceAnnouncement(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatPosition.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatPosition.CONSTRUCTOR);
			if (this.list == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.list.serialize(output);
			}
			output.writeLong(this.order);
			output.writeBoolean(this.isPinned);
			if (this.source == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.source.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatPosition chatPosition = (ChatPosition) o;
			if (!Objects.equals(this.list, chatPosition.list)) {
				return false;
			}
			if (this.order != chatPosition.order) {
				return false;
			}
			if (this.isPinned != chatPosition.isPinned) {
				return false;
			}
			if (!Objects.equals(this.source, chatPosition.source)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.order);
			result = result * 31 + (this.list == null ? 0 : this.list.hashCode());
			result = result * 31 + (this.source == null ? 0 : this.source.hashCode());
			return result;
		}
	}

	/**
	 * The chat contains spam messages.
	**/
	public static final class ChatReportReasonSpam extends ChatReportReason {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -510848863;

		/**
		 * The chat contains spam messages.
		**/
		public ChatReportReasonSpam() {}

		/**
		 * The chat contains spam messages.
		 *
		**/

		/**
		 * The chat contains spam messages.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatReportReasonSpam(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatReportReasonSpam.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatReportReasonSpam.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ChatReportReasonSpam.CONSTRUCTOR;
		}
	}

	/**
	 * The chat promotes violence.
	**/
	public static final class ChatReportReasonViolence extends ChatReportReason {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1330235395;

		/**
		 * The chat promotes violence.
		**/
		public ChatReportReasonViolence() {}

		/**
		 * The chat promotes violence.
		 *
		**/

		/**
		 * The chat promotes violence.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatReportReasonViolence(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatReportReasonViolence.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatReportReasonViolence.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ChatReportReasonViolence.CONSTRUCTOR;
		}
	}

	/**
	 * The chat contains pornographic messages.
	**/
	public static final class ChatReportReasonPornography extends ChatReportReason {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 722614385;

		/**
		 * The chat contains pornographic messages.
		**/
		public ChatReportReasonPornography() {}

		/**
		 * The chat contains pornographic messages.
		 *
		**/

		/**
		 * The chat contains pornographic messages.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatReportReasonPornography(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatReportReasonPornography.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatReportReasonPornography.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ChatReportReasonPornography.CONSTRUCTOR;
		}
	}

	/**
	 * The chat has child abuse related content.
	**/
	public static final class ChatReportReasonChildAbuse extends ChatReportReason {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1070686531;

		/**
		 * The chat has child abuse related content.
		**/
		public ChatReportReasonChildAbuse() {}

		/**
		 * The chat has child abuse related content.
		 *
		**/

		/**
		 * The chat has child abuse related content.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatReportReasonChildAbuse(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatReportReasonChildAbuse.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatReportReasonChildAbuse.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ChatReportReasonChildAbuse.CONSTRUCTOR;
		}
	}

	/**
	 * The chat contains copyrighted content.
	**/
	public static final class ChatReportReasonCopyright extends ChatReportReason {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 986898080;

		/**
		 * The chat contains copyrighted content.
		**/
		public ChatReportReasonCopyright() {}

		/**
		 * The chat contains copyrighted content.
		 *
		**/

		/**
		 * The chat contains copyrighted content.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatReportReasonCopyright(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatReportReasonCopyright.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatReportReasonCopyright.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ChatReportReasonCopyright.CONSTRUCTOR;
		}
	}

	/**
	 * The location-based chat is unrelated to its stated location.
	**/
	public static final class ChatReportReasonUnrelatedLocation extends ChatReportReason {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2632403;

		/**
		 * The location-based chat is unrelated to its stated location.
		**/
		public ChatReportReasonUnrelatedLocation() {}

		/**
		 * The location-based chat is unrelated to its stated location.
		 *
		**/

		/**
		 * The location-based chat is unrelated to its stated location.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatReportReasonUnrelatedLocation(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatReportReasonUnrelatedLocation.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatReportReasonUnrelatedLocation.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ChatReportReasonUnrelatedLocation.CONSTRUCTOR;
		}
	}

	/**
	 * The chat represents a fake account.
	**/
	public static final class ChatReportReasonFake extends ChatReportReason {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1713230446;

		/**
		 * The chat represents a fake account.
		**/
		public ChatReportReasonFake() {}

		/**
		 * The chat represents a fake account.
		 *
		**/

		/**
		 * The chat represents a fake account.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatReportReasonFake(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatReportReasonFake.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatReportReasonFake.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ChatReportReasonFake.CONSTRUCTOR;
		}
	}

	/**
	 * The chat has illegal drugs related content.
	**/
	public static final class ChatReportReasonIllegalDrugs extends ChatReportReason {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -844539307;

		/**
		 * The chat has illegal drugs related content.
		**/
		public ChatReportReasonIllegalDrugs() {}

		/**
		 * The chat has illegal drugs related content.
		 *
		**/

		/**
		 * The chat has illegal drugs related content.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatReportReasonIllegalDrugs(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatReportReasonIllegalDrugs.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatReportReasonIllegalDrugs.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ChatReportReasonIllegalDrugs.CONSTRUCTOR;
		}
	}

	/**
	 * The chat contains messages with personal details.
	**/
	public static final class ChatReportReasonPersonalDetails extends ChatReportReason {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1121159029;

		/**
		 * The chat contains messages with personal details.
		**/
		public ChatReportReasonPersonalDetails() {}

		/**
		 * The chat contains messages with personal details.
		 *
		**/

		/**
		 * The chat contains messages with personal details.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatReportReasonPersonalDetails(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatReportReasonPersonalDetails.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatReportReasonPersonalDetails.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ChatReportReasonPersonalDetails.CONSTRUCTOR;
		}
	}

	/**
	 * A custom reason provided by the user.
	**/
	public static final class ChatReportReasonCustom extends ChatReportReason {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1288925974;

		/**
		 * A custom reason provided by the user.
		**/
		public ChatReportReasonCustom() {}

		/**
		 * A custom reason provided by the user.
		 *
		**/

		/**
		 * A custom reason provided by the user.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatReportReasonCustom(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatReportReasonCustom.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatReportReasonCustom.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ChatReportReasonCustom.CONSTRUCTOR;
		}
	}

	/**
	 * The chat is sponsored by the user&#039;s MTProxy server.
	**/
	public static final class ChatSourceMtprotoProxy extends ChatSource {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 394074115;

		/**
		 * The chat is sponsored by the user&#039;s MTProxy server.
		**/
		public ChatSourceMtprotoProxy() {}

		/**
		 * The chat is sponsored by the user&#039;s MTProxy server.
		 *
		**/

		/**
		 * The chat is sponsored by the user&#039;s MTProxy server.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatSourceMtprotoProxy(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatSourceMtprotoProxy.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatSourceMtprotoProxy.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ChatSourceMtprotoProxy.CONSTRUCTOR;
		}
	}

	/**
	 * The chat contains a public service announcement.
	**/
	public static final class ChatSourcePublicServiceAnnouncement extends ChatSource {


		/**
		 * The type of the announcement.
		**/
		public String type;

		/**
		 * The text of the announcement.
		**/
		public String text;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -328571244;

		/**
		 * The chat contains a public service announcement.
		**/
		public ChatSourcePublicServiceAnnouncement() {}

		/**
		 * The chat contains a public service announcement.
		 *
		 * @param type The type of the announcement.
		 * @param text The text of the announcement.
		**/
		public ChatSourcePublicServiceAnnouncement(String type, String text) {
			this.type = type;
			this.text = text;
		}

		/**
		 * The chat contains a public service announcement.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatSourcePublicServiceAnnouncement(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] typeTmp = new byte[input.readInt()];
				input.readFully(typeTmp);
				this.type = new String(typeTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] textTmp = new byte[input.readInt()];
				input.readFully(textTmp);
				this.text = new String(textTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatSourcePublicServiceAnnouncement.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatSourcePublicServiceAnnouncement.CONSTRUCTOR);
			if (this.type == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] typeTmp = this.type.getBytes(StandardCharsets.UTF_8);
				output.writeInt(typeTmp.length);
				output.write(typeTmp);
			}
			if (this.text == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] textTmp = this.text.getBytes(StandardCharsets.UTF_8);
				output.writeInt(textTmp.length);
				output.write(textTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatSourcePublicServiceAnnouncement chatSourcePublicServiceAnnouncement = (ChatSourcePublicServiceAnnouncement) o;
			if (this.type != chatSourcePublicServiceAnnouncement.type) {
				return false;
			}
			if (this.text != chatSourcePublicServiceAnnouncement.text) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.type == null ? 0 : this.type.hashCode();
			result = result * 31 + (this.text == null ? 0 : this.text.hashCode());
			return result;
		}
	}

	/**
	 * A detailed statistics about a supergroup chat.
	**/
	public static final class ChatStatisticsSupergroup extends ChatStatistics {


		/**
		 * A period to which the statistics applies.
		**/
		public DateRange period;

		/**
		 * Number of members in the chat.
		**/
		public StatisticalValue memberCount;

		/**
		 * Number of messages sent to the chat.
		**/
		public StatisticalValue messageCount;

		/**
		 * Number of users who viewed messages in the chat.
		**/
		public StatisticalValue viewerCount;

		/**
		 * Number of users who sent messages to the chat.
		**/
		public StatisticalValue senderCount;

		/**
		 * A graph containing number of members in the chat.
		**/
		public StatisticalGraph memberCountGraph;

		/**
		 * A graph containing number of members joined and left the chat.
		**/
		public StatisticalGraph joinGraph;

		/**
		 * A graph containing number of new member joins per source.
		**/
		public StatisticalGraph joinBySourceGraph;

		/**
		 * A graph containing distribution of active users per language.
		**/
		public StatisticalGraph languageGraph;

		/**
		 * A graph containing distribution of sent messages by content type.
		**/
		public StatisticalGraph messageContentGraph;

		/**
		 * A graph containing number of different actions in the chat.
		**/
		public StatisticalGraph actionGraph;

		/**
		 * A graph containing distribution of message views per hour.
		**/
		public StatisticalGraph dayGraph;

		/**
		 * A graph containing distribution of message views per day of week.
		**/
		public StatisticalGraph weekGraph;

		/**
		 * List of users sent most messages in the last week.
		**/
		public ChatStatisticsMessageSenderInfo[] topSenders;

		/**
		 * List of most active administrators in the last week.
		**/
		public ChatStatisticsAdministratorActionsInfo[] topAdministrators;

		/**
		 * List of most active inviters of new members in the last week.
		**/
		public ChatStatisticsInviterInfo[] topInviters;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -17244633;

		/**
		 * A detailed statistics about a supergroup chat.
		**/
		public ChatStatisticsSupergroup() {}

		/**
		 * A detailed statistics about a supergroup chat.
		 *
		 * @param period A period to which the statistics applies.
		 * @param memberCount Number of members in the chat.
		 * @param messageCount Number of messages sent to the chat.
		 * @param viewerCount Number of users who viewed messages in the chat.
		 * @param senderCount Number of users who sent messages to the chat.
		 * @param memberCountGraph A graph containing number of members in the chat.
		 * @param joinGraph A graph containing number of members joined and left the chat.
		 * @param joinBySourceGraph A graph containing number of new member joins per source.
		 * @param languageGraph A graph containing distribution of active users per language.
		 * @param messageContentGraph A graph containing distribution of sent messages by content type.
		 * @param actionGraph A graph containing number of different actions in the chat.
		 * @param dayGraph A graph containing distribution of message views per hour.
		 * @param weekGraph A graph containing distribution of message views per day of week.
		 * @param topSenders List of users sent most messages in the last week.
		 * @param topAdministrators List of most active administrators in the last week.
		 * @param topInviters List of most active inviters of new members in the last week.
		**/
		public ChatStatisticsSupergroup(DateRange period,
				StatisticalValue memberCount,
				StatisticalValue messageCount,
				StatisticalValue viewerCount,
				StatisticalValue senderCount,
				StatisticalGraph memberCountGraph,
				StatisticalGraph joinGraph,
				StatisticalGraph joinBySourceGraph,
				StatisticalGraph languageGraph,
				StatisticalGraph messageContentGraph,
				StatisticalGraph actionGraph,
				StatisticalGraph dayGraph,
				StatisticalGraph weekGraph,
				ChatStatisticsMessageSenderInfo[] topSenders,
				ChatStatisticsAdministratorActionsInfo[] topAdministrators,
				ChatStatisticsInviterInfo[] topInviters) {
			this.period = period;
			this.memberCount = memberCount;
			this.messageCount = messageCount;
			this.viewerCount = viewerCount;
			this.senderCount = senderCount;
			this.memberCountGraph = memberCountGraph;
			this.joinGraph = joinGraph;
			this.joinBySourceGraph = joinBySourceGraph;
			this.languageGraph = languageGraph;
			this.messageContentGraph = messageContentGraph;
			this.actionGraph = actionGraph;
			this.dayGraph = dayGraph;
			this.weekGraph = weekGraph;
			this.topSenders = topSenders;
			this.topAdministrators = topAdministrators;
			this.topInviters = topInviters;
		}

		/**
		 * A detailed statistics about a supergroup chat.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatStatisticsSupergroup(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (DateRange.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.period = new DateRange(input);
			}
			if (input.readBoolean()) {
				if (StatisticalValue.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.memberCount = new StatisticalValue(input);
			}
			if (input.readBoolean()) {
				if (StatisticalValue.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.messageCount = new StatisticalValue(input);
			}
			if (input.readBoolean()) {
				if (StatisticalValue.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.viewerCount = new StatisticalValue(input);
			}
			if (input.readBoolean()) {
				if (StatisticalValue.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.senderCount = new StatisticalValue(input);
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case StatisticalGraphData.CONSTRUCTOR: this.memberCountGraph = new StatisticalGraphData(input); break;
					case StatisticalGraphAsync.CONSTRUCTOR: this.memberCountGraph = new StatisticalGraphAsync(input); break;
					case StatisticalGraphError.CONSTRUCTOR: this.memberCountGraph = new StatisticalGraphError(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case StatisticalGraphData.CONSTRUCTOR: this.joinGraph = new StatisticalGraphData(input); break;
					case StatisticalGraphAsync.CONSTRUCTOR: this.joinGraph = new StatisticalGraphAsync(input); break;
					case StatisticalGraphError.CONSTRUCTOR: this.joinGraph = new StatisticalGraphError(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case StatisticalGraphData.CONSTRUCTOR: this.joinBySourceGraph = new StatisticalGraphData(input); break;
					case StatisticalGraphAsync.CONSTRUCTOR: this.joinBySourceGraph = new StatisticalGraphAsync(input); break;
					case StatisticalGraphError.CONSTRUCTOR: this.joinBySourceGraph = new StatisticalGraphError(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case StatisticalGraphData.CONSTRUCTOR: this.languageGraph = new StatisticalGraphData(input); break;
					case StatisticalGraphAsync.CONSTRUCTOR: this.languageGraph = new StatisticalGraphAsync(input); break;
					case StatisticalGraphError.CONSTRUCTOR: this.languageGraph = new StatisticalGraphError(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case StatisticalGraphData.CONSTRUCTOR: this.messageContentGraph = new StatisticalGraphData(input); break;
					case StatisticalGraphAsync.CONSTRUCTOR: this.messageContentGraph = new StatisticalGraphAsync(input); break;
					case StatisticalGraphError.CONSTRUCTOR: this.messageContentGraph = new StatisticalGraphError(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case StatisticalGraphData.CONSTRUCTOR: this.actionGraph = new StatisticalGraphData(input); break;
					case StatisticalGraphAsync.CONSTRUCTOR: this.actionGraph = new StatisticalGraphAsync(input); break;
					case StatisticalGraphError.CONSTRUCTOR: this.actionGraph = new StatisticalGraphError(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case StatisticalGraphData.CONSTRUCTOR: this.dayGraph = new StatisticalGraphData(input); break;
					case StatisticalGraphAsync.CONSTRUCTOR: this.dayGraph = new StatisticalGraphAsync(input); break;
					case StatisticalGraphError.CONSTRUCTOR: this.dayGraph = new StatisticalGraphError(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case StatisticalGraphData.CONSTRUCTOR: this.weekGraph = new StatisticalGraphData(input); break;
					case StatisticalGraphAsync.CONSTRUCTOR: this.weekGraph = new StatisticalGraphAsync(input); break;
					case StatisticalGraphError.CONSTRUCTOR: this.weekGraph = new StatisticalGraphError(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				this.topSenders = new ChatStatisticsMessageSenderInfo[input.readInt()];
				for (int i = 0; i < this.topSenders.length; i++) {
					if (ChatStatisticsMessageSenderInfo.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.topSenders[i] = new ChatStatisticsMessageSenderInfo(input);
				}
			}
			if (input.readBoolean()) {
				this.topAdministrators = new ChatStatisticsAdministratorActionsInfo[input.readInt()];
				for (int i = 0; i < this.topAdministrators.length; i++) {
					if (ChatStatisticsAdministratorActionsInfo.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.topAdministrators[i] = new ChatStatisticsAdministratorActionsInfo(input);
				}
			}
			if (input.readBoolean()) {
				this.topInviters = new ChatStatisticsInviterInfo[input.readInt()];
				for (int i = 0; i < this.topInviters.length; i++) {
					if (ChatStatisticsInviterInfo.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.topInviters[i] = new ChatStatisticsInviterInfo(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatStatisticsSupergroup.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatStatisticsSupergroup.CONSTRUCTOR);
			if (this.period == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.period.serialize(output);
			}
			if (this.memberCount == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.memberCount.serialize(output);
			}
			if (this.messageCount == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.messageCount.serialize(output);
			}
			if (this.viewerCount == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.viewerCount.serialize(output);
			}
			if (this.senderCount == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.senderCount.serialize(output);
			}
			if (this.memberCountGraph == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.memberCountGraph.serialize(output);
			}
			if (this.joinGraph == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.joinGraph.serialize(output);
			}
			if (this.joinBySourceGraph == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.joinBySourceGraph.serialize(output);
			}
			if (this.languageGraph == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.languageGraph.serialize(output);
			}
			if (this.messageContentGraph == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.messageContentGraph.serialize(output);
			}
			if (this.actionGraph == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.actionGraph.serialize(output);
			}
			if (this.dayGraph == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.dayGraph.serialize(output);
			}
			if (this.weekGraph == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.weekGraph.serialize(output);
			}
			if (this.topSenders == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.topSenders.length);
				for (int i = 0; i < this.topSenders.length; i++) {
					this.topSenders[i].serialize(output);
				}
			}
			if (this.topAdministrators == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.topAdministrators.length);
				for (int i = 0; i < this.topAdministrators.length; i++) {
					this.topAdministrators[i].serialize(output);
				}
			}
			if (this.topInviters == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.topInviters.length);
				for (int i = 0; i < this.topInviters.length; i++) {
					this.topInviters[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatStatisticsSupergroup chatStatisticsSupergroup = (ChatStatisticsSupergroup) o;
			if (!Objects.equals(this.period, chatStatisticsSupergroup.period)) {
				return false;
			}
			if (!Objects.equals(this.memberCount, chatStatisticsSupergroup.memberCount)) {
				return false;
			}
			if (!Objects.equals(this.messageCount, chatStatisticsSupergroup.messageCount)) {
				return false;
			}
			if (!Objects.equals(this.viewerCount, chatStatisticsSupergroup.viewerCount)) {
				return false;
			}
			if (!Objects.equals(this.senderCount, chatStatisticsSupergroup.senderCount)) {
				return false;
			}
			if (!Objects.equals(this.memberCountGraph, chatStatisticsSupergroup.memberCountGraph)) {
				return false;
			}
			if (!Objects.equals(this.joinGraph, chatStatisticsSupergroup.joinGraph)) {
				return false;
			}
			if (!Objects.equals(this.joinBySourceGraph, chatStatisticsSupergroup.joinBySourceGraph)) {
				return false;
			}
			if (!Objects.equals(this.languageGraph, chatStatisticsSupergroup.languageGraph)) {
				return false;
			}
			if (!Objects.equals(this.messageContentGraph, chatStatisticsSupergroup.messageContentGraph)) {
				return false;
			}
			if (!Objects.equals(this.actionGraph, chatStatisticsSupergroup.actionGraph)) {
				return false;
			}
			if (!Objects.equals(this.dayGraph, chatStatisticsSupergroup.dayGraph)) {
				return false;
			}
			if (!Objects.equals(this.weekGraph, chatStatisticsSupergroup.weekGraph)) {
				return false;
			}
			if (!Arrays.equals(this.topSenders, chatStatisticsSupergroup.topSenders)) {
				return false;
			}
			if (!Arrays.equals(this.topAdministrators, chatStatisticsSupergroup.topAdministrators)) {
				return false;
			}
			if (!Arrays.equals(this.topInviters, chatStatisticsSupergroup.topInviters)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.period == null ? 0 : this.period.hashCode();
			result = result * 31 + (this.memberCount == null ? 0 : this.memberCount.hashCode());
			result = result * 31 + (this.messageCount == null ? 0 : this.messageCount.hashCode());
			result = result * 31 + (this.viewerCount == null ? 0 : this.viewerCount.hashCode());
			result = result * 31 + (this.senderCount == null ? 0 : this.senderCount.hashCode());
			result = result * 31 + (this.memberCountGraph == null ? 0 : this.memberCountGraph.hashCode());
			result = result * 31 + (this.joinGraph == null ? 0 : this.joinGraph.hashCode());
			result = result * 31 + (this.joinBySourceGraph == null ? 0 : this.joinBySourceGraph.hashCode());
			result = result * 31 + (this.languageGraph == null ? 0 : this.languageGraph.hashCode());
			result = result * 31 + (this.messageContentGraph == null ? 0 : this.messageContentGraph.hashCode());
			result = result * 31 + (this.actionGraph == null ? 0 : this.actionGraph.hashCode());
			result = result * 31 + (this.dayGraph == null ? 0 : this.dayGraph.hashCode());
			result = result * 31 + (this.weekGraph == null ? 0 : this.weekGraph.hashCode());
			result = result * 31 + (Arrays.hashCode(this.topSenders));
			result = result * 31 + (Arrays.hashCode(this.topAdministrators));
			result = result * 31 + (Arrays.hashCode(this.topInviters));
			return result;
		}
	}

	/**
	 * A detailed statistics about a channel chat.
	**/
	public static final class ChatStatisticsChannel extends ChatStatistics {


		/**
		 * A period to which the statistics applies.
		**/
		public DateRange period;

		/**
		 * Number of members in the chat.
		**/
		public StatisticalValue memberCount;

		/**
		 * Mean number of times the recently sent messages was viewed.
		**/
		public StatisticalValue meanViewCount;

		/**
		 * Mean number of times the recently sent messages was shared.
		**/
		public StatisticalValue meanShareCount;

		/**
		 * A percentage of users with enabled notifications for the chat.
		**/
		public double enabledNotificationsPercentage;

		/**
		 * A graph containing number of members in the chat.
		**/
		public StatisticalGraph memberCountGraph;

		/**
		 * A graph containing number of members joined and left the chat.
		**/
		public StatisticalGraph joinGraph;

		/**
		 * A graph containing number of members muted and unmuted the chat.
		**/
		public StatisticalGraph muteGraph;

		/**
		 * A graph containing number of message views in a given hour in the last two weeks.
		**/
		public StatisticalGraph viewCountByHourGraph;

		/**
		 * A graph containing number of message views per source.
		**/
		public StatisticalGraph viewCountBySourceGraph;

		/**
		 * A graph containing number of new member joins per source.
		**/
		public StatisticalGraph joinBySourceGraph;

		/**
		 * A graph containing number of users viewed chat messages per language.
		**/
		public StatisticalGraph languageGraph;

		/**
		 * A graph containing number of chat message views and shares.
		**/
		public StatisticalGraph messageInteractionGraph;

		/**
		 * A graph containing number of views of associated with the chat instant views.
		**/
		public StatisticalGraph instantViewInteractionGraph;

		/**
		 * Detailed statistics about number of views and shares of recently sent messages.
		**/
		public ChatStatisticsMessageInteractionInfo[] recentMessageInteractions;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -825434183;

		/**
		 * A detailed statistics about a channel chat.
		**/
		public ChatStatisticsChannel() {}

		/**
		 * A detailed statistics about a channel chat.
		 *
		 * @param period A period to which the statistics applies.
		 * @param memberCount Number of members in the chat.
		 * @param meanViewCount Mean number of times the recently sent messages was viewed.
		 * @param meanShareCount Mean number of times the recently sent messages was shared.
		 * @param enabledNotificationsPercentage A percentage of users with enabled notifications for the chat.
		 * @param memberCountGraph A graph containing number of members in the chat.
		 * @param joinGraph A graph containing number of members joined and left the chat.
		 * @param muteGraph A graph containing number of members muted and unmuted the chat.
		 * @param viewCountByHourGraph A graph containing number of message views in a given hour in the last two weeks.
		 * @param viewCountBySourceGraph A graph containing number of message views per source.
		 * @param joinBySourceGraph A graph containing number of new member joins per source.
		 * @param languageGraph A graph containing number of users viewed chat messages per language.
		 * @param messageInteractionGraph A graph containing number of chat message views and shares.
		 * @param instantViewInteractionGraph A graph containing number of views of associated with the chat instant views.
		 * @param recentMessageInteractions Detailed statistics about number of views and shares of recently sent messages.
		**/
		public ChatStatisticsChannel(DateRange period,
				StatisticalValue memberCount,
				StatisticalValue meanViewCount,
				StatisticalValue meanShareCount,
				double enabledNotificationsPercentage,
				StatisticalGraph memberCountGraph,
				StatisticalGraph joinGraph,
				StatisticalGraph muteGraph,
				StatisticalGraph viewCountByHourGraph,
				StatisticalGraph viewCountBySourceGraph,
				StatisticalGraph joinBySourceGraph,
				StatisticalGraph languageGraph,
				StatisticalGraph messageInteractionGraph,
				StatisticalGraph instantViewInteractionGraph,
				ChatStatisticsMessageInteractionInfo[] recentMessageInteractions) {
			this.period = period;
			this.memberCount = memberCount;
			this.meanViewCount = meanViewCount;
			this.meanShareCount = meanShareCount;
			this.enabledNotificationsPercentage = enabledNotificationsPercentage;
			this.memberCountGraph = memberCountGraph;
			this.joinGraph = joinGraph;
			this.muteGraph = muteGraph;
			this.viewCountByHourGraph = viewCountByHourGraph;
			this.viewCountBySourceGraph = viewCountBySourceGraph;
			this.joinBySourceGraph = joinBySourceGraph;
			this.languageGraph = languageGraph;
			this.messageInteractionGraph = messageInteractionGraph;
			this.instantViewInteractionGraph = instantViewInteractionGraph;
			this.recentMessageInteractions = recentMessageInteractions;
		}

		/**
		 * A detailed statistics about a channel chat.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatStatisticsChannel(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (DateRange.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.period = new DateRange(input);
			}
			if (input.readBoolean()) {
				if (StatisticalValue.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.memberCount = new StatisticalValue(input);
			}
			if (input.readBoolean()) {
				if (StatisticalValue.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.meanViewCount = new StatisticalValue(input);
			}
			if (input.readBoolean()) {
				if (StatisticalValue.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.meanShareCount = new StatisticalValue(input);
			}
			this.enabledNotificationsPercentage = input.readDouble();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case StatisticalGraphData.CONSTRUCTOR: this.memberCountGraph = new StatisticalGraphData(input); break;
					case StatisticalGraphAsync.CONSTRUCTOR: this.memberCountGraph = new StatisticalGraphAsync(input); break;
					case StatisticalGraphError.CONSTRUCTOR: this.memberCountGraph = new StatisticalGraphError(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case StatisticalGraphData.CONSTRUCTOR: this.joinGraph = new StatisticalGraphData(input); break;
					case StatisticalGraphAsync.CONSTRUCTOR: this.joinGraph = new StatisticalGraphAsync(input); break;
					case StatisticalGraphError.CONSTRUCTOR: this.joinGraph = new StatisticalGraphError(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case StatisticalGraphData.CONSTRUCTOR: this.muteGraph = new StatisticalGraphData(input); break;
					case StatisticalGraphAsync.CONSTRUCTOR: this.muteGraph = new StatisticalGraphAsync(input); break;
					case StatisticalGraphError.CONSTRUCTOR: this.muteGraph = new StatisticalGraphError(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case StatisticalGraphData.CONSTRUCTOR: this.viewCountByHourGraph = new StatisticalGraphData(input); break;
					case StatisticalGraphAsync.CONSTRUCTOR: this.viewCountByHourGraph = new StatisticalGraphAsync(input); break;
					case StatisticalGraphError.CONSTRUCTOR: this.viewCountByHourGraph = new StatisticalGraphError(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case StatisticalGraphData.CONSTRUCTOR: this.viewCountBySourceGraph = new StatisticalGraphData(input); break;
					case StatisticalGraphAsync.CONSTRUCTOR: this.viewCountBySourceGraph = new StatisticalGraphAsync(input); break;
					case StatisticalGraphError.CONSTRUCTOR: this.viewCountBySourceGraph = new StatisticalGraphError(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case StatisticalGraphData.CONSTRUCTOR: this.joinBySourceGraph = new StatisticalGraphData(input); break;
					case StatisticalGraphAsync.CONSTRUCTOR: this.joinBySourceGraph = new StatisticalGraphAsync(input); break;
					case StatisticalGraphError.CONSTRUCTOR: this.joinBySourceGraph = new StatisticalGraphError(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case StatisticalGraphData.CONSTRUCTOR: this.languageGraph = new StatisticalGraphData(input); break;
					case StatisticalGraphAsync.CONSTRUCTOR: this.languageGraph = new StatisticalGraphAsync(input); break;
					case StatisticalGraphError.CONSTRUCTOR: this.languageGraph = new StatisticalGraphError(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case StatisticalGraphData.CONSTRUCTOR: this.messageInteractionGraph = new StatisticalGraphData(input); break;
					case StatisticalGraphAsync.CONSTRUCTOR: this.messageInteractionGraph = new StatisticalGraphAsync(input); break;
					case StatisticalGraphError.CONSTRUCTOR: this.messageInteractionGraph = new StatisticalGraphError(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case StatisticalGraphData.CONSTRUCTOR: this.instantViewInteractionGraph = new StatisticalGraphData(input); break;
					case StatisticalGraphAsync.CONSTRUCTOR: this.instantViewInteractionGraph = new StatisticalGraphAsync(input); break;
					case StatisticalGraphError.CONSTRUCTOR: this.instantViewInteractionGraph = new StatisticalGraphError(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				this.recentMessageInteractions = new ChatStatisticsMessageInteractionInfo[input.readInt()];
				for (int i = 0; i < this.recentMessageInteractions.length; i++) {
					if (ChatStatisticsMessageInteractionInfo.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.recentMessageInteractions[i] = new ChatStatisticsMessageInteractionInfo(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatStatisticsChannel.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatStatisticsChannel.CONSTRUCTOR);
			if (this.period == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.period.serialize(output);
			}
			if (this.memberCount == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.memberCount.serialize(output);
			}
			if (this.meanViewCount == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.meanViewCount.serialize(output);
			}
			if (this.meanShareCount == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.meanShareCount.serialize(output);
			}
			output.writeDouble(this.enabledNotificationsPercentage);
			if (this.memberCountGraph == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.memberCountGraph.serialize(output);
			}
			if (this.joinGraph == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.joinGraph.serialize(output);
			}
			if (this.muteGraph == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.muteGraph.serialize(output);
			}
			if (this.viewCountByHourGraph == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.viewCountByHourGraph.serialize(output);
			}
			if (this.viewCountBySourceGraph == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.viewCountBySourceGraph.serialize(output);
			}
			if (this.joinBySourceGraph == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.joinBySourceGraph.serialize(output);
			}
			if (this.languageGraph == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.languageGraph.serialize(output);
			}
			if (this.messageInteractionGraph == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.messageInteractionGraph.serialize(output);
			}
			if (this.instantViewInteractionGraph == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.instantViewInteractionGraph.serialize(output);
			}
			if (this.recentMessageInteractions == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.recentMessageInteractions.length);
				for (int i = 0; i < this.recentMessageInteractions.length; i++) {
					this.recentMessageInteractions[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatStatisticsChannel chatStatisticsChannel = (ChatStatisticsChannel) o;
			if (!Objects.equals(this.period, chatStatisticsChannel.period)) {
				return false;
			}
			if (!Objects.equals(this.memberCount, chatStatisticsChannel.memberCount)) {
				return false;
			}
			if (!Objects.equals(this.meanViewCount, chatStatisticsChannel.meanViewCount)) {
				return false;
			}
			if (!Objects.equals(this.meanShareCount, chatStatisticsChannel.meanShareCount)) {
				return false;
			}
			if (this.enabledNotificationsPercentage != chatStatisticsChannel.enabledNotificationsPercentage) {
				return false;
			}
			if (!Objects.equals(this.memberCountGraph, chatStatisticsChannel.memberCountGraph)) {
				return false;
			}
			if (!Objects.equals(this.joinGraph, chatStatisticsChannel.joinGraph)) {
				return false;
			}
			if (!Objects.equals(this.muteGraph, chatStatisticsChannel.muteGraph)) {
				return false;
			}
			if (!Objects.equals(this.viewCountByHourGraph, chatStatisticsChannel.viewCountByHourGraph)) {
				return false;
			}
			if (!Objects.equals(this.viewCountBySourceGraph, chatStatisticsChannel.viewCountBySourceGraph)) {
				return false;
			}
			if (!Objects.equals(this.joinBySourceGraph, chatStatisticsChannel.joinBySourceGraph)) {
				return false;
			}
			if (!Objects.equals(this.languageGraph, chatStatisticsChannel.languageGraph)) {
				return false;
			}
			if (!Objects.equals(this.messageInteractionGraph, chatStatisticsChannel.messageInteractionGraph)) {
				return false;
			}
			if (!Objects.equals(this.instantViewInteractionGraph, chatStatisticsChannel.instantViewInteractionGraph)) {
				return false;
			}
			if (!Arrays.equals(this.recentMessageInteractions, chatStatisticsChannel.recentMessageInteractions)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Double.hashCode(this.enabledNotificationsPercentage);
			result = result * 31 + (this.period == null ? 0 : this.period.hashCode());
			result = result * 31 + (this.memberCount == null ? 0 : this.memberCount.hashCode());
			result = result * 31 + (this.meanViewCount == null ? 0 : this.meanViewCount.hashCode());
			result = result * 31 + (this.meanShareCount == null ? 0 : this.meanShareCount.hashCode());
			result = result * 31 + (this.memberCountGraph == null ? 0 : this.memberCountGraph.hashCode());
			result = result * 31 + (this.joinGraph == null ? 0 : this.joinGraph.hashCode());
			result = result * 31 + (this.muteGraph == null ? 0 : this.muteGraph.hashCode());
			result = result * 31 + (this.viewCountByHourGraph == null ? 0 : this.viewCountByHourGraph.hashCode());
			result = result * 31 + (this.viewCountBySourceGraph == null ? 0 : this.viewCountBySourceGraph.hashCode());
			result = result * 31 + (this.joinBySourceGraph == null ? 0 : this.joinBySourceGraph.hashCode());
			result = result * 31 + (this.languageGraph == null ? 0 : this.languageGraph.hashCode());
			result = result * 31 + (this.messageInteractionGraph == null ? 0 : this.messageInteractionGraph.hashCode());
			result = result * 31 + (this.instantViewInteractionGraph == null ? 0 : this.instantViewInteractionGraph.hashCode());
			result = result * 31 + (Arrays.hashCode(this.recentMessageInteractions));
			return result;
		}
	}

	/**
	 * Contains statistics about administrator actions done by a user.
	**/
	public static final class ChatStatisticsAdministratorActionsInfo extends Object {


		/**
		 * Administrator user identifier.
		**/
		public long userId;

		/**
		 * Number of messages deleted by the administrator.
		**/
		public int deletedMessageCount;

		/**
		 * Number of users banned by the administrator.
		**/
		public int bannedUserCount;

		/**
		 * Number of users restricted by the administrator.
		**/
		public int restrictedUserCount;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -406467202;

		/**
		 * Contains statistics about administrator actions done by a user.
		**/
		public ChatStatisticsAdministratorActionsInfo() {}

		/**
		 * Contains statistics about administrator actions done by a user.
		 *
		 * @param userId Administrator user identifier.
		 * @param deletedMessageCount Number of messages deleted by the administrator.
		 * @param bannedUserCount Number of users banned by the administrator.
		 * @param restrictedUserCount Number of users restricted by the administrator.
		**/
		public ChatStatisticsAdministratorActionsInfo(long userId,
				int deletedMessageCount,
				int bannedUserCount,
				int restrictedUserCount) {
			this.userId = userId;
			this.deletedMessageCount = deletedMessageCount;
			this.bannedUserCount = bannedUserCount;
			this.restrictedUserCount = restrictedUserCount;
		}

		/**
		 * Contains statistics about administrator actions done by a user.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatStatisticsAdministratorActionsInfo(DataInput input) throws IOException {
			this.userId = input.readLong();
			this.deletedMessageCount = input.readInt();
			this.bannedUserCount = input.readInt();
			this.restrictedUserCount = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatStatisticsAdministratorActionsInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatStatisticsAdministratorActionsInfo.CONSTRUCTOR);
			output.writeLong(this.userId);
			output.writeInt(this.deletedMessageCount);
			output.writeInt(this.bannedUserCount);
			output.writeInt(this.restrictedUserCount);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatStatisticsAdministratorActionsInfo chatStatisticsAdministratorActionsInfo = (ChatStatisticsAdministratorActionsInfo) o;
			if (this.userId != chatStatisticsAdministratorActionsInfo.userId) {
				return false;
			}
			if (this.deletedMessageCount != chatStatisticsAdministratorActionsInfo.deletedMessageCount) {
				return false;
			}
			if (this.bannedUserCount != chatStatisticsAdministratorActionsInfo.bannedUserCount) {
				return false;
			}
			if (this.restrictedUserCount != chatStatisticsAdministratorActionsInfo.restrictedUserCount) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.userId);
			return result;
		}
	}

	/**
	 * Contains statistics about number of new members invited by a user.
	**/
	public static final class ChatStatisticsInviterInfo extends Object {


		/**
		 * User identifier.
		**/
		public long userId;

		/**
		 * Number of new members invited by the user.
		**/
		public int addedMemberCount;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 629396619;

		/**
		 * Contains statistics about number of new members invited by a user.
		**/
		public ChatStatisticsInviterInfo() {}

		/**
		 * Contains statistics about number of new members invited by a user.
		 *
		 * @param userId User identifier.
		 * @param addedMemberCount Number of new members invited by the user.
		**/
		public ChatStatisticsInviterInfo(long userId, int addedMemberCount) {
			this.userId = userId;
			this.addedMemberCount = addedMemberCount;
		}

		/**
		 * Contains statistics about number of new members invited by a user.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatStatisticsInviterInfo(DataInput input) throws IOException {
			this.userId = input.readLong();
			this.addedMemberCount = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatStatisticsInviterInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatStatisticsInviterInfo.CONSTRUCTOR);
			output.writeLong(this.userId);
			output.writeInt(this.addedMemberCount);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatStatisticsInviterInfo chatStatisticsInviterInfo = (ChatStatisticsInviterInfo) o;
			if (this.userId != chatStatisticsInviterInfo.userId) {
				return false;
			}
			if (this.addedMemberCount != chatStatisticsInviterInfo.addedMemberCount) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.userId);
			return result;
		}
	}

	/**
	 * Contains statistics about interactions with a message.
	**/
	public static final class ChatStatisticsMessageInteractionInfo extends Object {


		/**
		 * Message identifier.
		**/
		public long messageId;

		/**
		 * Number of times the message was viewed.
		**/
		public int viewCount;

		/**
		 * Number of times the message was forwarded.
		**/
		public int forwardCount;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -765580756;

		/**
		 * Contains statistics about interactions with a message.
		**/
		public ChatStatisticsMessageInteractionInfo() {}

		/**
		 * Contains statistics about interactions with a message.
		 *
		 * @param messageId Message identifier.
		 * @param viewCount Number of times the message was viewed.
		 * @param forwardCount Number of times the message was forwarded.
		**/
		public ChatStatisticsMessageInteractionInfo(long messageId, int viewCount, int forwardCount) {
			this.messageId = messageId;
			this.viewCount = viewCount;
			this.forwardCount = forwardCount;
		}

		/**
		 * Contains statistics about interactions with a message.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatStatisticsMessageInteractionInfo(DataInput input) throws IOException {
			this.messageId = input.readLong();
			this.viewCount = input.readInt();
			this.forwardCount = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatStatisticsMessageInteractionInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatStatisticsMessageInteractionInfo.CONSTRUCTOR);
			output.writeLong(this.messageId);
			output.writeInt(this.viewCount);
			output.writeInt(this.forwardCount);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatStatisticsMessageInteractionInfo chatStatisticsMessageInteractionInfo = (ChatStatisticsMessageInteractionInfo) o;
			if (this.messageId != chatStatisticsMessageInteractionInfo.messageId) {
				return false;
			}
			if (this.viewCount != chatStatisticsMessageInteractionInfo.viewCount) {
				return false;
			}
			if (this.forwardCount != chatStatisticsMessageInteractionInfo.forwardCount) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.messageId);
			return result;
		}
	}

	/**
	 * Contains statistics about messages sent by a user.
	**/
	public static final class ChatStatisticsMessageSenderInfo extends Object {


		/**
		 * User identifier.
		**/
		public long userId;

		/**
		 * Number of sent messages.
		**/
		public int sentMessageCount;

		/**
		 * Average number of characters in sent messages; 0 if unknown.
		**/
		public int averageCharacterCount;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1762295371;

		/**
		 * Contains statistics about messages sent by a user.
		**/
		public ChatStatisticsMessageSenderInfo() {}

		/**
		 * Contains statistics about messages sent by a user.
		 *
		 * @param userId User identifier.
		 * @param sentMessageCount Number of sent messages.
		 * @param averageCharacterCount Average number of characters in sent messages; 0 if unknown.
		**/
		public ChatStatisticsMessageSenderInfo(long userId, int sentMessageCount, int averageCharacterCount) {
			this.userId = userId;
			this.sentMessageCount = sentMessageCount;
			this.averageCharacterCount = averageCharacterCount;
		}

		/**
		 * Contains statistics about messages sent by a user.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatStatisticsMessageSenderInfo(DataInput input) throws IOException {
			this.userId = input.readLong();
			this.sentMessageCount = input.readInt();
			this.averageCharacterCount = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatStatisticsMessageSenderInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatStatisticsMessageSenderInfo.CONSTRUCTOR);
			output.writeLong(this.userId);
			output.writeInt(this.sentMessageCount);
			output.writeInt(this.averageCharacterCount);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatStatisticsMessageSenderInfo chatStatisticsMessageSenderInfo = (ChatStatisticsMessageSenderInfo) o;
			if (this.userId != chatStatisticsMessageSenderInfo.userId) {
				return false;
			}
			if (this.sentMessageCount != chatStatisticsMessageSenderInfo.sentMessageCount) {
				return false;
			}
			if (this.averageCharacterCount != chatStatisticsMessageSenderInfo.averageCharacterCount) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.userId);
			return result;
		}
	}

	/**
	 * Describes a chat theme.
	**/
	public static final class ChatTheme extends Object {


		/**
		 * Theme name.
		**/
		public String name;

		/**
		 * Theme settings for a light chat theme.
		**/
		public ThemeSettings lightSettings;

		/**
		 * Theme settings for a dark chat theme.
		**/
		public ThemeSettings darkSettings;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -113218503;

		/**
		 * Describes a chat theme.
		**/
		public ChatTheme() {}

		/**
		 * Describes a chat theme.
		 *
		 * @param name Theme name.
		 * @param lightSettings Theme settings for a light chat theme.
		 * @param darkSettings Theme settings for a dark chat theme.
		**/
		public ChatTheme(String name,
				ThemeSettings lightSettings,
				ThemeSettings darkSettings) {
			this.name = name;
			this.lightSettings = lightSettings;
			this.darkSettings = darkSettings;
		}

		/**
		 * Describes a chat theme.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatTheme(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] nameTmp = new byte[input.readInt()];
				input.readFully(nameTmp);
				this.name = new String(nameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (ThemeSettings.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.lightSettings = new ThemeSettings(input);
			}
			if (input.readBoolean()) {
				if (ThemeSettings.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.darkSettings = new ThemeSettings(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatTheme.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatTheme.CONSTRUCTOR);
			if (this.name == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nameTmp = this.name.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nameTmp.length);
				output.write(nameTmp);
			}
			if (this.lightSettings == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.lightSettings.serialize(output);
			}
			if (this.darkSettings == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.darkSettings.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatTheme chatTheme = (ChatTheme) o;
			if (this.name != chatTheme.name) {
				return false;
			}
			if (!Objects.equals(this.lightSettings, chatTheme.lightSettings)) {
				return false;
			}
			if (!Objects.equals(this.darkSettings, chatTheme.darkSettings)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.name == null ? 0 : this.name.hashCode();
			result = result * 31 + (this.lightSettings == null ? 0 : this.lightSettings.hashCode());
			result = result * 31 + (this.darkSettings == null ? 0 : this.darkSettings.hashCode());
			return result;
		}
	}

	/**
	 * An ordinary chat with a user.
	**/
	public static final class ChatTypePrivate extends ChatType {


		/**
		 * User identifier.
		**/
		public long userId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1579049844;

		/**
		 * An ordinary chat with a user.
		**/
		public ChatTypePrivate() {}

		/**
		 * An ordinary chat with a user.
		 *
		 * @param userId User identifier.
		**/
		public ChatTypePrivate(long userId) {
			this.userId = userId;
		}

		/**
		 * An ordinary chat with a user.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatTypePrivate(DataInput input) throws IOException {
			this.userId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatTypePrivate.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatTypePrivate.CONSTRUCTOR);
			output.writeLong(this.userId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatTypePrivate chatTypePrivate = (ChatTypePrivate) o;
			if (this.userId != chatTypePrivate.userId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.userId);
		}
	}

	/**
	 * A basic group (a chat with 0-200 other users).
	**/
	public static final class ChatTypeBasicGroup extends ChatType {


		/**
		 * Basic group identifier.
		**/
		public long basicGroupId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 973884508;

		/**
		 * A basic group (a chat with 0-200 other users).
		**/
		public ChatTypeBasicGroup() {}

		/**
		 * A basic group (a chat with 0-200 other users).
		 *
		 * @param basicGroupId Basic group identifier.
		**/
		public ChatTypeBasicGroup(long basicGroupId) {
			this.basicGroupId = basicGroupId;
		}

		/**
		 * A basic group (a chat with 0-200 other users).
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatTypeBasicGroup(DataInput input) throws IOException {
			this.basicGroupId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatTypeBasicGroup.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatTypeBasicGroup.CONSTRUCTOR);
			output.writeLong(this.basicGroupId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatTypeBasicGroup chatTypeBasicGroup = (ChatTypeBasicGroup) o;
			if (this.basicGroupId != chatTypeBasicGroup.basicGroupId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.basicGroupId);
		}
	}

	/**
	 * A supergroup or channel (with unlimited members).
	**/
	public static final class ChatTypeSupergroup extends ChatType {


		/**
		 * Supergroup or channel identifier.
		**/
		public long supergroupId;

		/**
		 * True, if the supergroup is a channel.
		**/
		public boolean isChannel;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1472570774;

		/**
		 * A supergroup or channel (with unlimited members).
		**/
		public ChatTypeSupergroup() {}

		/**
		 * A supergroup or channel (with unlimited members).
		 *
		 * @param supergroupId Supergroup or channel identifier.
		 * @param isChannel True, if the supergroup is a channel.
		**/
		public ChatTypeSupergroup(long supergroupId, boolean isChannel) {
			this.supergroupId = supergroupId;
			this.isChannel = isChannel;
		}

		/**
		 * A supergroup or channel (with unlimited members).
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatTypeSupergroup(DataInput input) throws IOException {
			this.supergroupId = input.readLong();
			this.isChannel = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatTypeSupergroup.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatTypeSupergroup.CONSTRUCTOR);
			output.writeLong(this.supergroupId);
			output.writeBoolean(this.isChannel);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatTypeSupergroup chatTypeSupergroup = (ChatTypeSupergroup) o;
			if (this.supergroupId != chatTypeSupergroup.supergroupId) {
				return false;
			}
			if (this.isChannel != chatTypeSupergroup.isChannel) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.supergroupId);
			return result;
		}
	}

	/**
	 * A secret chat with a user.
	**/
	public static final class ChatTypeSecret extends ChatType {


		/**
		 * Secret chat identifier.
		**/
		public int secretChatId;

		/**
		 * User identifier of the secret chat peer.
		**/
		public long userId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 862366513;

		/**
		 * A secret chat with a user.
		**/
		public ChatTypeSecret() {}

		/**
		 * A secret chat with a user.
		 *
		 * @param secretChatId Secret chat identifier.
		 * @param userId User identifier of the secret chat peer.
		**/
		public ChatTypeSecret(int secretChatId, long userId) {
			this.secretChatId = secretChatId;
			this.userId = userId;
		}

		/**
		 * A secret chat with a user.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatTypeSecret(DataInput input) throws IOException {
			this.secretChatId = input.readInt();
			this.userId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatTypeSecret.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatTypeSecret.CONSTRUCTOR);
			output.writeInt(this.secretChatId);
			output.writeLong(this.userId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatTypeSecret chatTypeSecret = (ChatTypeSecret) o;
			if (this.secretChatId != chatTypeSecret.secretChatId) {
				return false;
			}
			if (this.userId != chatTypeSecret.userId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.secretChatId);
			return result;
		}
	}

	/**
	 * Represents a list of chats.
	**/
	public static final class Chats extends Object {


		/**
		 * Approximate total number of chats found.
		**/
		public int totalCount;

		/**
		 * List of chat identifiers.
		**/
		public long[] chatIds;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1809654812;

		/**
		 * Represents a list of chats.
		**/
		public Chats() {}

		/**
		 * Represents a list of chats.
		 *
		 * @param totalCount Approximate total number of chats found.
		 * @param chatIds List of chat identifiers.
		**/
		public Chats(int totalCount, long[] chatIds) {
			this.totalCount = totalCount;
			this.chatIds = chatIds;
		}

		/**
		 * Represents a list of chats.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public Chats(DataInput input) throws IOException {
			this.totalCount = input.readInt();
			if (input.readBoolean()) {
				this.chatIds = new long[input.readInt()];
				for (int i = 0; i < this.chatIds.length; i++) {
					this.chatIds[i] = input.readLong();
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return Chats.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(Chats.CONSTRUCTOR);
			output.writeInt(this.totalCount);
			if (this.chatIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.chatIds.length);
				for (int i = 0; i < this.chatIds.length; i++) {
					output.writeLong(this.chatIds[i]);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			Chats chats = (Chats) o;
			if (this.totalCount != chats.totalCount) {
				return false;
			}
			if (!Arrays.equals(this.chatIds, chats.chatIds)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.totalCount);
			result = result * 31 + (Arrays.hashCode(this.chatIds));
			return result;
		}
	}

	/**
	 * Represents a list of chats located nearby.
	**/
	public static final class ChatsNearby extends Object {


		/**
		 * List of users nearby.
		**/
		public ChatNearby[] usersNearby;

		/**
		 * List of location-based supergroups nearby.
		**/
		public ChatNearby[] supergroupsNearby;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 187746081;

		/**
		 * Represents a list of chats located nearby.
		**/
		public ChatsNearby() {}

		/**
		 * Represents a list of chats located nearby.
		 *
		 * @param usersNearby List of users nearby.
		 * @param supergroupsNearby List of location-based supergroups nearby.
		**/
		public ChatsNearby(ChatNearby[] usersNearby, ChatNearby[] supergroupsNearby) {
			this.usersNearby = usersNearby;
			this.supergroupsNearby = supergroupsNearby;
		}

		/**
		 * Represents a list of chats located nearby.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChatsNearby(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.usersNearby = new ChatNearby[input.readInt()];
				for (int i = 0; i < this.usersNearby.length; i++) {
					if (ChatNearby.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.usersNearby[i] = new ChatNearby(input);
				}
			}
			if (input.readBoolean()) {
				this.supergroupsNearby = new ChatNearby[input.readInt()];
				for (int i = 0; i < this.supergroupsNearby.length; i++) {
					if (ChatNearby.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.supergroupsNearby[i] = new ChatNearby(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChatsNearby.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChatsNearby.CONSTRUCTOR);
			if (this.usersNearby == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.usersNearby.length);
				for (int i = 0; i < this.usersNearby.length; i++) {
					this.usersNearby[i].serialize(output);
				}
			}
			if (this.supergroupsNearby == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.supergroupsNearby.length);
				for (int i = 0; i < this.supergroupsNearby.length; i++) {
					this.supergroupsNearby[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChatsNearby chatsNearby = (ChatsNearby) o;
			if (!Arrays.equals(this.usersNearby, chatsNearby.usersNearby)) {
				return false;
			}
			if (!Arrays.equals(this.supergroupsNearby, chatsNearby.supergroupsNearby)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Arrays.hashCode(this.usersNearby);
			result = result * 31 + (Arrays.hashCode(this.supergroupsNearby));
			return result;
		}
	}

	/**
	 * The username can be set.
	**/
	public static final class CheckChatUsernameResultOk extends CheckChatUsernameResult {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1498956964;

		/**
		 * The username can be set.
		**/
		public CheckChatUsernameResultOk() {}

		/**
		 * The username can be set.
		 *
		**/

		/**
		 * The username can be set.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CheckChatUsernameResultOk(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CheckChatUsernameResultOk.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CheckChatUsernameResultOk.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return CheckChatUsernameResultOk.CONSTRUCTOR;
		}
	}

	/**
	 * The username is invalid.
	**/
	public static final class CheckChatUsernameResultUsernameInvalid extends CheckChatUsernameResult {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -636979370;

		/**
		 * The username is invalid.
		**/
		public CheckChatUsernameResultUsernameInvalid() {}

		/**
		 * The username is invalid.
		 *
		**/

		/**
		 * The username is invalid.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CheckChatUsernameResultUsernameInvalid(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CheckChatUsernameResultUsernameInvalid.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CheckChatUsernameResultUsernameInvalid.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return CheckChatUsernameResultUsernameInvalid.CONSTRUCTOR;
		}
	}

	/**
	 * The username is occupied.
	**/
	public static final class CheckChatUsernameResultUsernameOccupied extends CheckChatUsernameResult {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1320892201;

		/**
		 * The username is occupied.
		**/
		public CheckChatUsernameResultUsernameOccupied() {}

		/**
		 * The username is occupied.
		 *
		**/

		/**
		 * The username is occupied.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CheckChatUsernameResultUsernameOccupied(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CheckChatUsernameResultUsernameOccupied.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CheckChatUsernameResultUsernameOccupied.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return CheckChatUsernameResultUsernameOccupied.CONSTRUCTOR;
		}
	}

	/**
	 * The username can be purchased at fragment.com.
	**/
	public static final class CheckChatUsernameResultUsernamePurchasable extends CheckChatUsernameResult {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 5885529;

		/**
		 * The username can be purchased at fragment.com.
		**/
		public CheckChatUsernameResultUsernamePurchasable() {}

		/**
		 * The username can be purchased at fragment.com.
		 *
		**/

		/**
		 * The username can be purchased at fragment.com.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CheckChatUsernameResultUsernamePurchasable(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CheckChatUsernameResultUsernamePurchasable.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CheckChatUsernameResultUsernamePurchasable.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return CheckChatUsernameResultUsernamePurchasable.CONSTRUCTOR;
		}
	}

	/**
	 * The user has too many chats with username, one of them must be made
	 * private first.
	**/
	public static final class CheckChatUsernameResultPublicChatsTooMany extends CheckChatUsernameResult {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -659264388;

		/**
		 * The user has too many chats with username, one of them must be made private first.
		**/
		public CheckChatUsernameResultPublicChatsTooMany() {}

		/**
		 * The user has too many chats with username, one of them must be made private first.
		 *
		**/

		/**
		 * The user has too many chats with username, one of them must be made private first.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CheckChatUsernameResultPublicChatsTooMany(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CheckChatUsernameResultPublicChatsTooMany.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CheckChatUsernameResultPublicChatsTooMany.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return CheckChatUsernameResultPublicChatsTooMany.CONSTRUCTOR;
		}
	}

	/**
	 * The user can&#039;t be a member of a public supergroup.
	**/
	public static final class CheckChatUsernameResultPublicGroupsUnavailable extends CheckChatUsernameResult {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -51833641;

		/**
		 * The user can&#039;t be a member of a public supergroup.
		**/
		public CheckChatUsernameResultPublicGroupsUnavailable() {}

		/**
		 * The user can&#039;t be a member of a public supergroup.
		 *
		**/

		/**
		 * The user can&#039;t be a member of a public supergroup.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CheckChatUsernameResultPublicGroupsUnavailable(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CheckChatUsernameResultPublicGroupsUnavailable.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CheckChatUsernameResultPublicGroupsUnavailable.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return CheckChatUsernameResultPublicGroupsUnavailable.CONSTRUCTOR;
		}
	}

	/**
	 * The name can be set.
	**/
	public static final class CheckStickerSetNameResultOk extends CheckStickerSetNameResult {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1404308904;

		/**
		 * The name can be set.
		**/
		public CheckStickerSetNameResultOk() {}

		/**
		 * The name can be set.
		 *
		**/

		/**
		 * The name can be set.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CheckStickerSetNameResultOk(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CheckStickerSetNameResultOk.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CheckStickerSetNameResultOk.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return CheckStickerSetNameResultOk.CONSTRUCTOR;
		}
	}

	/**
	 * The name is invalid.
	**/
	public static final class CheckStickerSetNameResultNameInvalid extends CheckStickerSetNameResult {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 177992244;

		/**
		 * The name is invalid.
		**/
		public CheckStickerSetNameResultNameInvalid() {}

		/**
		 * The name is invalid.
		 *
		**/

		/**
		 * The name is invalid.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CheckStickerSetNameResultNameInvalid(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CheckStickerSetNameResultNameInvalid.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CheckStickerSetNameResultNameInvalid.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return CheckStickerSetNameResultNameInvalid.CONSTRUCTOR;
		}
	}

	/**
	 * The name is occupied.
	**/
	public static final class CheckStickerSetNameResultNameOccupied extends CheckStickerSetNameResult {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1012980872;

		/**
		 * The name is occupied.
		**/
		public CheckStickerSetNameResultNameOccupied() {}

		/**
		 * The name is occupied.
		 *
		**/

		/**
		 * The name is occupied.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CheckStickerSetNameResultNameOccupied(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CheckStickerSetNameResultNameOccupied.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CheckStickerSetNameResultNameOccupied.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return CheckStickerSetNameResultNameOccupied.CONSTRUCTOR;
		}
	}

	/**
	 * Represents a closed vector path. The path begins at the end point of
	 * the last command.
	**/
	public static final class ClosedVectorPath extends Object {


		/**
		 * List of vector path commands.
		**/
		public VectorPathCommand[] commands;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 589951657;

		/**
		 * Represents a closed vector path. The path begins at the end point of the last command.
		**/
		public ClosedVectorPath() {}

		/**
		 * Represents a closed vector path. The path begins at the end point of the last command.
		 *
		 * @param commands List of vector path commands.
		**/
		public ClosedVectorPath(VectorPathCommand[] commands) {
			this.commands = commands;
		}

		/**
		 * Represents a closed vector path. The path begins at the end point of the last command.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ClosedVectorPath(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.commands = new VectorPathCommand[input.readInt()];
				for (int i = 0; i < this.commands.length; i++) {
					switch(input.readInt()) {
						case VectorPathCommandLine.CONSTRUCTOR: this.commands[i] = new VectorPathCommandLine(input); break;
						case VectorPathCommandCubicBezierCurve.CONSTRUCTOR: this.commands[i] = new VectorPathCommandCubicBezierCurve(input); break;
						default: {
							throw new UnsupportedOperationException();
						}
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ClosedVectorPath.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ClosedVectorPath.CONSTRUCTOR);
			if (this.commands == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.commands.length);
				for (int i = 0; i < this.commands.length; i++) {
					this.commands[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ClosedVectorPath closedVectorPath = (ClosedVectorPath) o;
			if (!Arrays.equals(this.commands, closedVectorPath.commands)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.commands);
		}
	}

	/**
	 * Contains information about one website the current user is logged in
	 * with Telegram.
	**/
	public static final class ConnectedWebsite extends Object {


		/**
		 * Website identifier.
		**/
		public long id;

		/**
		 * The domain name of the website.
		**/
		public String domainName;

		/**
		 * User identifier of a bot linked with the website.
		**/
		public long botUserId;

		/**
		 * The version of a browser used to log in.
		**/
		public String browser;

		/**
		 * Operating system the browser is running on.
		**/
		public String platform;

		/**
		 * Point in time (Unix timestamp) when the user was logged in.
		**/
		public int logInDate;

		/**
		 * Point in time (Unix timestamp) when obtained authorization was last used.
		**/
		public int lastActiveDate;

		/**
		 * IP address from which the user was logged in, in human-readable format.
		**/
		public String ip;

		/**
		 * Human-readable description of a country and a region from which the user was logged in, based on the IP address.
		**/
		public String location;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 844014445;

		/**
		 * Contains information about one website the current user is logged in with Telegram.
		**/
		public ConnectedWebsite() {}

		/**
		 * Contains information about one website the current user is logged in with Telegram.
		 *
		 * @param id Website identifier.
		 * @param domainName The domain name of the website.
		 * @param botUserId User identifier of a bot linked with the website.
		 * @param browser The version of a browser used to log in.
		 * @param platform Operating system the browser is running on.
		 * @param logInDate Point in time (Unix timestamp) when the user was logged in.
		 * @param lastActiveDate Point in time (Unix timestamp) when obtained authorization was last used.
		 * @param ip IP address from which the user was logged in, in human-readable format.
		 * @param location Human-readable description of a country and a region from which the user was logged in, based on the IP address.
		**/
		public ConnectedWebsite(long id,
				String domainName,
				long botUserId,
				String browser,
				String platform,
				int logInDate,
				int lastActiveDate,
				String ip,
				String location) {
			this.id = id;
			this.domainName = domainName;
			this.botUserId = botUserId;
			this.browser = browser;
			this.platform = platform;
			this.logInDate = logInDate;
			this.lastActiveDate = lastActiveDate;
			this.ip = ip;
			this.location = location;
		}

		/**
		 * Contains information about one website the current user is logged in with Telegram.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ConnectedWebsite(DataInput input) throws IOException {
			this.id = input.readLong();
			if (input.readBoolean()) {
				byte[] domainNameTmp = new byte[input.readInt()];
				input.readFully(domainNameTmp);
				this.domainName = new String(domainNameTmp, StandardCharsets.UTF_8);
			}
			this.botUserId = input.readLong();
			if (input.readBoolean()) {
				byte[] browserTmp = new byte[input.readInt()];
				input.readFully(browserTmp);
				this.browser = new String(browserTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] platformTmp = new byte[input.readInt()];
				input.readFully(platformTmp);
				this.platform = new String(platformTmp, StandardCharsets.UTF_8);
			}
			this.logInDate = input.readInt();
			this.lastActiveDate = input.readInt();
			if (input.readBoolean()) {
				byte[] ipTmp = new byte[input.readInt()];
				input.readFully(ipTmp);
				this.ip = new String(ipTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] locationTmp = new byte[input.readInt()];
				input.readFully(locationTmp);
				this.location = new String(locationTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ConnectedWebsite.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ConnectedWebsite.CONSTRUCTOR);
			output.writeLong(this.id);
			if (this.domainName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] domainNameTmp = this.domainName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(domainNameTmp.length);
				output.write(domainNameTmp);
			}
			output.writeLong(this.botUserId);
			if (this.browser == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] browserTmp = this.browser.getBytes(StandardCharsets.UTF_8);
				output.writeInt(browserTmp.length);
				output.write(browserTmp);
			}
			if (this.platform == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] platformTmp = this.platform.getBytes(StandardCharsets.UTF_8);
				output.writeInt(platformTmp.length);
				output.write(platformTmp);
			}
			output.writeInt(this.logInDate);
			output.writeInt(this.lastActiveDate);
			if (this.ip == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] ipTmp = this.ip.getBytes(StandardCharsets.UTF_8);
				output.writeInt(ipTmp.length);
				output.write(ipTmp);
			}
			if (this.location == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] locationTmp = this.location.getBytes(StandardCharsets.UTF_8);
				output.writeInt(locationTmp.length);
				output.write(locationTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ConnectedWebsite connectedWebsite = (ConnectedWebsite) o;
			if (this.id != connectedWebsite.id) {
				return false;
			}
			if (this.domainName != connectedWebsite.domainName) {
				return false;
			}
			if (this.botUserId != connectedWebsite.botUserId) {
				return false;
			}
			if (this.browser != connectedWebsite.browser) {
				return false;
			}
			if (this.platform != connectedWebsite.platform) {
				return false;
			}
			if (this.logInDate != connectedWebsite.logInDate) {
				return false;
			}
			if (this.lastActiveDate != connectedWebsite.lastActiveDate) {
				return false;
			}
			if (this.ip != connectedWebsite.ip) {
				return false;
			}
			if (this.location != connectedWebsite.location) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.id);
			result = result * 31 + (this.domainName == null ? 0 : this.domainName.hashCode());
			result = result * 31 + (this.browser == null ? 0 : this.browser.hashCode());
			result = result * 31 + (this.platform == null ? 0 : this.platform.hashCode());
			result = result * 31 + (this.ip == null ? 0 : this.ip.hashCode());
			result = result * 31 + (this.location == null ? 0 : this.location.hashCode());
			return result;
		}
	}

	/**
	 * Contains a list of websites the current user is logged in with
	 * Telegram.
	**/
	public static final class ConnectedWebsites extends Object {


		/**
		 * List of connected websites.
		**/
		public ConnectedWebsite[] websites;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1727949694;

		/**
		 * Contains a list of websites the current user is logged in with Telegram.
		**/
		public ConnectedWebsites() {}

		/**
		 * Contains a list of websites the current user is logged in with Telegram.
		 *
		 * @param websites List of connected websites.
		**/
		public ConnectedWebsites(ConnectedWebsite[] websites) {
			this.websites = websites;
		}

		/**
		 * Contains a list of websites the current user is logged in with Telegram.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ConnectedWebsites(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.websites = new ConnectedWebsite[input.readInt()];
				for (int i = 0; i < this.websites.length; i++) {
					if (ConnectedWebsite.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.websites[i] = new ConnectedWebsite(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ConnectedWebsites.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ConnectedWebsites.CONSTRUCTOR);
			if (this.websites == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.websites.length);
				for (int i = 0; i < this.websites.length; i++) {
					this.websites[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ConnectedWebsites connectedWebsites = (ConnectedWebsites) o;
			if (!Arrays.equals(this.websites, connectedWebsites.websites)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.websites);
		}
	}

	/**
	 * Currently waiting for the network to become available. Use
	 * setNetworkType to change the available network type.
	**/
	public static final class ConnectionStateWaitingForNetwork extends ConnectionState {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1695405912;

		/**
		 * Currently waiting for the network to become available. Use setNetworkType to change the available network type.
		**/
		public ConnectionStateWaitingForNetwork() {}

		/**
		 * Currently waiting for the network to become available. Use setNetworkType to change the available network type.
		 *
		**/

		/**
		 * Currently waiting for the network to become available. Use setNetworkType to change the available network type.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ConnectionStateWaitingForNetwork(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ConnectionStateWaitingForNetwork.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ConnectionStateWaitingForNetwork.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ConnectionStateWaitingForNetwork.CONSTRUCTOR;
		}
	}

	/**
	 * Currently establishing a connection with a proxy server.
	**/
	public static final class ConnectionStateConnectingToProxy extends ConnectionState {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -93187239;

		/**
		 * Currently establishing a connection with a proxy server.
		**/
		public ConnectionStateConnectingToProxy() {}

		/**
		 * Currently establishing a connection with a proxy server.
		 *
		**/

		/**
		 * Currently establishing a connection with a proxy server.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ConnectionStateConnectingToProxy(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ConnectionStateConnectingToProxy.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ConnectionStateConnectingToProxy.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ConnectionStateConnectingToProxy.CONSTRUCTOR;
		}
	}

	/**
	 * Currently establishing a connection to the Telegram servers.
	**/
	public static final class ConnectionStateConnecting extends ConnectionState {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1298400670;

		/**
		 * Currently establishing a connection to the Telegram servers.
		**/
		public ConnectionStateConnecting() {}

		/**
		 * Currently establishing a connection to the Telegram servers.
		 *
		**/

		/**
		 * Currently establishing a connection to the Telegram servers.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ConnectionStateConnecting(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ConnectionStateConnecting.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ConnectionStateConnecting.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ConnectionStateConnecting.CONSTRUCTOR;
		}
	}

	/**
	 * Downloading data received while the application was offline.
	**/
	public static final class ConnectionStateUpdating extends ConnectionState {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -188104009;

		/**
		 * Downloading data received while the application was offline.
		**/
		public ConnectionStateUpdating() {}

		/**
		 * Downloading data received while the application was offline.
		 *
		**/

		/**
		 * Downloading data received while the application was offline.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ConnectionStateUpdating(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ConnectionStateUpdating.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ConnectionStateUpdating.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ConnectionStateUpdating.CONSTRUCTOR;
		}
	}

	/**
	 * There is a working connection to the Telegram servers.
	**/
	public static final class ConnectionStateReady extends ConnectionState {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 48608492;

		/**
		 * There is a working connection to the Telegram servers.
		**/
		public ConnectionStateReady() {}

		/**
		 * There is a working connection to the Telegram servers.
		 *
		**/

		/**
		 * There is a working connection to the Telegram servers.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ConnectionStateReady(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ConnectionStateReady.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ConnectionStateReady.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ConnectionStateReady.CONSTRUCTOR;
		}
	}

	/**
	 * Describes a user contact.
	**/
	public static final class Contact extends Object {


		/**
		 * Phone number of the user.
		**/
		public String phoneNumber;

		/**
		 * First name of the user; 1-255 characters in length.
		**/
		public String firstName;

		/**
		 * Last name of the user.
		**/
		public String lastName;

		/**
		 * Additional data about the user in a form of vCard; 0-2048 bytes in length.
		**/
		public String vcard;

		/**
		 * Identifier of the user, if known; 0 otherwise.
		**/
		public long userId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1993844876;

		/**
		 * Describes a user contact.
		**/
		public Contact() {}

		/**
		 * Describes a user contact.
		 *
		 * @param phoneNumber Phone number of the user.
		 * @param firstName First name of the user; 1-255 characters in length.
		 * @param lastName Last name of the user.
		 * @param vcard Additional data about the user in a form of vCard; 0-2048 bytes in length.
		 * @param userId Identifier of the user, if known; 0 otherwise.
		**/
		public Contact(String phoneNumber,
				String firstName,
				String lastName,
				String vcard,
				long userId) {
			this.phoneNumber = phoneNumber;
			this.firstName = firstName;
			this.lastName = lastName;
			this.vcard = vcard;
			this.userId = userId;
		}

		/**
		 * Describes a user contact.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public Contact(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] phoneNumberTmp = new byte[input.readInt()];
				input.readFully(phoneNumberTmp);
				this.phoneNumber = new String(phoneNumberTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] firstNameTmp = new byte[input.readInt()];
				input.readFully(firstNameTmp);
				this.firstName = new String(firstNameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] lastNameTmp = new byte[input.readInt()];
				input.readFully(lastNameTmp);
				this.lastName = new String(lastNameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] vcardTmp = new byte[input.readInt()];
				input.readFully(vcardTmp);
				this.vcard = new String(vcardTmp, StandardCharsets.UTF_8);
			}
			this.userId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return Contact.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(Contact.CONSTRUCTOR);
			if (this.phoneNumber == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] phoneNumberTmp = this.phoneNumber.getBytes(StandardCharsets.UTF_8);
				output.writeInt(phoneNumberTmp.length);
				output.write(phoneNumberTmp);
			}
			if (this.firstName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] firstNameTmp = this.firstName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(firstNameTmp.length);
				output.write(firstNameTmp);
			}
			if (this.lastName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] lastNameTmp = this.lastName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(lastNameTmp.length);
				output.write(lastNameTmp);
			}
			if (this.vcard == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] vcardTmp = this.vcard.getBytes(StandardCharsets.UTF_8);
				output.writeInt(vcardTmp.length);
				output.write(vcardTmp);
			}
			output.writeLong(this.userId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			Contact contact = (Contact) o;
			if (this.phoneNumber != contact.phoneNumber) {
				return false;
			}
			if (this.firstName != contact.firstName) {
				return false;
			}
			if (this.lastName != contact.lastName) {
				return false;
			}
			if (this.vcard != contact.vcard) {
				return false;
			}
			if (this.userId != contact.userId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.userId);
			result = result * 31 + (this.phoneNumber == null ? 0 : this.phoneNumber.hashCode());
			result = result * 31 + (this.firstName == null ? 0 : this.firstName.hashCode());
			result = result * 31 + (this.lastName == null ? 0 : this.lastName.hashCode());
			result = result * 31 + (this.vcard == null ? 0 : this.vcard.hashCode());
			return result;
		}
	}

	/**
	 * Contains a counter.
	**/
	public static final class Count extends Object {


		/**
		 * Count.
		**/
		public int count;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1295577348;

		/**
		 * Contains a counter.
		**/
		public Count() {}

		/**
		 * Contains a counter.
		 *
		 * @param count Count.
		**/
		public Count(int count) {
			this.count = count;
		}

		/**
		 * Contains a counter.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public Count(DataInput input) throws IOException {
			this.count = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return Count.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(Count.CONSTRUCTOR);
			output.writeInt(this.count);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			Count count = (Count) o;
			if (this.count != count.count) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.count);
		}
	}

	/**
	 * Contains information about countries.
	**/
	public static final class Countries extends Object {


		/**
		 * The list of countries.
		**/
		public CountryInfo[] countries;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1854211813;

		/**
		 * Contains information about countries.
		**/
		public Countries() {}

		/**
		 * Contains information about countries.
		 *
		 * @param countries The list of countries.
		**/
		public Countries(CountryInfo[] countries) {
			this.countries = countries;
		}

		/**
		 * Contains information about countries.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public Countries(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.countries = new CountryInfo[input.readInt()];
				for (int i = 0; i < this.countries.length; i++) {
					if (CountryInfo.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.countries[i] = new CountryInfo(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return Countries.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(Countries.CONSTRUCTOR);
			if (this.countries == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.countries.length);
				for (int i = 0; i < this.countries.length; i++) {
					this.countries[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			Countries countries = (Countries) o;
			if (!Arrays.equals(this.countries, countries.countries)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.countries);
		}
	}

	/**
	 * Contains information about a country.
	**/
	public static final class CountryInfo extends Object {


		/**
		 * A two-letter ISO 3166-1 alpha-2 country code.
		**/
		public String countryCode;

		/**
		 * Native name of the country.
		**/
		public String name;

		/**
		 * English name of the country.
		**/
		public String englishName;

		/**
		 * True, if the country must be hidden from the list of all countries.
		**/
		public boolean isHidden;

		/**
		 * List of country calling codes.
		**/
		public String[] callingCodes;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1617195722;

		/**
		 * Contains information about a country.
		**/
		public CountryInfo() {}

		/**
		 * Contains information about a country.
		 *
		 * @param countryCode A two-letter ISO 3166-1 alpha-2 country code.
		 * @param name Native name of the country.
		 * @param englishName English name of the country.
		 * @param isHidden True, if the country must be hidden from the list of all countries.
		 * @param callingCodes List of country calling codes.
		**/
		public CountryInfo(String countryCode,
				String name,
				String englishName,
				boolean isHidden,
				String[] callingCodes) {
			this.countryCode = countryCode;
			this.name = name;
			this.englishName = englishName;
			this.isHidden = isHidden;
			this.callingCodes = callingCodes;
		}

		/**
		 * Contains information about a country.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CountryInfo(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] countryCodeTmp = new byte[input.readInt()];
				input.readFully(countryCodeTmp);
				this.countryCode = new String(countryCodeTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] nameTmp = new byte[input.readInt()];
				input.readFully(nameTmp);
				this.name = new String(nameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] englishNameTmp = new byte[input.readInt()];
				input.readFully(englishNameTmp);
				this.englishName = new String(englishNameTmp, StandardCharsets.UTF_8);
			}
			this.isHidden = input.readBoolean();
			if (input.readBoolean()) {
				this.callingCodes = new String[input.readInt()];
				for (int i = 0; i < this.callingCodes.length; i++) {
					byte[] callingCodesTmp = new byte[input.readInt()];
					input.readFully(callingCodesTmp);
					this.callingCodes[i] = new String(callingCodesTmp, StandardCharsets.UTF_8);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CountryInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CountryInfo.CONSTRUCTOR);
			if (this.countryCode == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] countryCodeTmp = this.countryCode.getBytes(StandardCharsets.UTF_8);
				output.writeInt(countryCodeTmp.length);
				output.write(countryCodeTmp);
			}
			if (this.name == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nameTmp = this.name.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nameTmp.length);
				output.write(nameTmp);
			}
			if (this.englishName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] englishNameTmp = this.englishName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(englishNameTmp.length);
				output.write(englishNameTmp);
			}
			output.writeBoolean(this.isHidden);
			if (this.callingCodes == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.callingCodes.length);
				for (int i = 0; i < this.callingCodes.length; i++) {
					byte[] callingCodesTmp = this.callingCodes[i].getBytes(StandardCharsets.UTF_8);
					output.writeInt(callingCodesTmp.length);
					output.write(callingCodesTmp);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CountryInfo countryInfo = (CountryInfo) o;
			if (this.countryCode != countryInfo.countryCode) {
				return false;
			}
			if (this.name != countryInfo.name) {
				return false;
			}
			if (this.englishName != countryInfo.englishName) {
				return false;
			}
			if (this.isHidden != countryInfo.isHidden) {
				return false;
			}
			if (!Arrays.equals(this.callingCodes, countryInfo.callingCodes)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isHidden);
			result = result * 31 + (this.countryCode == null ? 0 : this.countryCode.hashCode());
			result = result * 31 + (this.name == null ? 0 : this.name.hashCode());
			result = result * 31 + (this.englishName == null ? 0 : this.englishName.hashCode());
			result = result * 31 + (Arrays.hashCode(this.callingCodes));
			return result;
		}
	}

	/**
	 * Contains the result of a custom request.
	**/
	public static final class CustomRequestResult extends Object {


		/**
		 * A JSON-serialized result.
		**/
		public String result;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2009960452;

		/**
		 * Contains the result of a custom request.
		**/
		public CustomRequestResult() {}

		/**
		 * Contains the result of a custom request.
		 *
		 * @param result A JSON-serialized result.
		**/
		public CustomRequestResult(String result) {
			this.result = result;
		}

		/**
		 * Contains the result of a custom request.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CustomRequestResult(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] resultTmp = new byte[input.readInt()];
				input.readFully(resultTmp);
				this.result = new String(resultTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CustomRequestResult.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CustomRequestResult.CONSTRUCTOR);
			if (this.result == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] resultTmp = this.result.getBytes(StandardCharsets.UTF_8);
				output.writeInt(resultTmp.length);
				output.write(resultTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CustomRequestResult customRequestResult = (CustomRequestResult) o;
			if (this.result != customRequestResult.result) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.result == null ? 0 : this.result.hashCode();
		}
	}

	/**
	 * Contains database statistics.
	**/
	public static final class DatabaseStatistics extends Object {


		/**
		 * Database statistics in an unspecified human-readable format.
		**/
		public String statistics;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1123912880;

		/**
		 * Contains database statistics.
		**/
		public DatabaseStatistics() {}

		/**
		 * Contains database statistics.
		 *
		 * @param statistics Database statistics in an unspecified human-readable format.
		**/
		public DatabaseStatistics(String statistics) {
			this.statistics = statistics;
		}

		/**
		 * Contains database statistics.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public DatabaseStatistics(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] statisticsTmp = new byte[input.readInt()];
				input.readFully(statisticsTmp);
				this.statistics = new String(statisticsTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return DatabaseStatistics.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(DatabaseStatistics.CONSTRUCTOR);
			if (this.statistics == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] statisticsTmp = this.statistics.getBytes(StandardCharsets.UTF_8);
				output.writeInt(statisticsTmp.length);
				output.write(statisticsTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			DatabaseStatistics databaseStatistics = (DatabaseStatistics) o;
			if (this.statistics != databaseStatistics.statistics) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.statistics == null ? 0 : this.statistics.hashCode();
		}
	}

	/**
	 * Represents a date according to the Gregorian calendar.
	**/
	public static final class Date extends Object {


		/**
		 * Day of the month; 1-31.
		**/
		public int day;

		/**
		 * Month; 1-12.
		**/
		public int month;

		/**
		 * Year; 1-9999.
		**/
		public int year;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -277956960;

		/**
		 * Represents a date according to the Gregorian calendar.
		**/
		public Date() {}

		/**
		 * Represents a date according to the Gregorian calendar.
		 *
		 * @param day Day of the month; 1-31.
		 * @param month Month; 1-12.
		 * @param year Year; 1-9999.
		**/
		public Date(int day, int month, int year) {
			this.day = day;
			this.month = month;
			this.year = year;
		}

		/**
		 * Represents a date according to the Gregorian calendar.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public Date(DataInput input) throws IOException {
			this.day = input.readInt();
			this.month = input.readInt();
			this.year = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return Date.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(Date.CONSTRUCTOR);
			output.writeInt(this.day);
			output.writeInt(this.month);
			output.writeInt(this.year);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			Date date = (Date) o;
			if (this.day != date.day) {
				return false;
			}
			if (this.month != date.month) {
				return false;
			}
			if (this.year != date.year) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.day);
			return result;
		}
	}

	/**
	 * Represents a date range.
	**/
	public static final class DateRange extends Object {


		/**
		 * Point in time (Unix timestamp) at which the date range begins.
		**/
		public int startDate;

		/**
		 * Point in time (Unix timestamp) at which the date range ends.
		**/
		public int endDate;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1360333926;

		/**
		 * Represents a date range.
		**/
		public DateRange() {}

		/**
		 * Represents a date range.
		 *
		 * @param startDate Point in time (Unix timestamp) at which the date range begins.
		 * @param endDate Point in time (Unix timestamp) at which the date range ends.
		**/
		public DateRange(int startDate, int endDate) {
			this.startDate = startDate;
			this.endDate = endDate;
		}

		/**
		 * Represents a date range.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public DateRange(DataInput input) throws IOException {
			this.startDate = input.readInt();
			this.endDate = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return DateRange.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(DateRange.CONSTRUCTOR);
			output.writeInt(this.startDate);
			output.writeInt(this.endDate);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			DateRange dateRange = (DateRange) o;
			if (this.startDate != dateRange.startDate) {
				return false;
			}
			if (this.endDate != dateRange.endDate) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.startDate);
			return result;
		}
	}

	/**
	 * File with the date it was uploaded.
	**/
	public static final class DatedFile extends Object {


		/**
		 * The file.
		**/
		public File file;

		/**
		 * Point in time (Unix timestamp) when the file was uploaded.
		**/
		public int date;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1840795491;

		/**
		 * File with the date it was uploaded.
		**/
		public DatedFile() {}

		/**
		 * File with the date it was uploaded.
		 *
		 * @param file The file.
		 * @param date Point in time (Unix timestamp) when the file was uploaded.
		**/
		public DatedFile(File file, int date) {
			this.file = file;
			this.date = date;
		}

		/**
		 * File with the date it was uploaded.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public DatedFile(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (File.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.file = new File(input);
			}
			this.date = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return DatedFile.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(DatedFile.CONSTRUCTOR);
			if (this.file == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.file.serialize(output);
			}
			output.writeInt(this.date);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			DatedFile datedFile = (DatedFile) o;
			if (!Objects.equals(this.file, datedFile.file)) {
				return false;
			}
			if (this.date != datedFile.date) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.date);
			result = result * 31 + (this.file == null ? 0 : this.file.hashCode());
			return result;
		}
	}

	/**
	 * Contains information about a tg: deep link.
	**/
	public static final class DeepLinkInfo extends Object {


		/**
		 * Text to be shown to the user.
		**/
		public FormattedText text;

		/**
		 * True, if the user must be asked to update the application.
		**/
		public boolean needUpdateApplication;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1864081662;

		/**
		 * Contains information about a tg: deep link.
		**/
		public DeepLinkInfo() {}

		/**
		 * Contains information about a tg: deep link.
		 *
		 * @param text Text to be shown to the user.
		 * @param needUpdateApplication True, if the user must be asked to update the application.
		**/
		public DeepLinkInfo(FormattedText text, boolean needUpdateApplication) {
			this.text = text;
			this.needUpdateApplication = needUpdateApplication;
		}

		/**
		 * Contains information about a tg: deep link.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public DeepLinkInfo(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (FormattedText.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.text = new FormattedText(input);
			}
			this.needUpdateApplication = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return DeepLinkInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(DeepLinkInfo.CONSTRUCTOR);
			if (this.text == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.text.serialize(output);
			}
			output.writeBoolean(this.needUpdateApplication);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			DeepLinkInfo deepLinkInfo = (DeepLinkInfo) o;
			if (!Objects.equals(this.text, deepLinkInfo.text)) {
				return false;
			}
			if (this.needUpdateApplication != deepLinkInfo.needUpdateApplication) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.needUpdateApplication);
			result = result * 31 + (this.text == null ? 0 : this.text.hashCode());
			return result;
		}
	}

	/**
	 * A token for Firebase Cloud Messaging.
	**/
	public static final class DeviceTokenFirebaseCloudMessaging extends DeviceToken {


		/**
		 * Device registration token; may be empty to deregister a device.
		**/
		public String token;

		/**
		 * True, if push notifications must be additionally encrypted.
		**/
		public boolean encrypt;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -797881849;

		/**
		 * A token for Firebase Cloud Messaging.
		**/
		public DeviceTokenFirebaseCloudMessaging() {}

		/**
		 * A token for Firebase Cloud Messaging.
		 *
		 * @param token Device registration token; may be empty to deregister a device.
		 * @param encrypt True, if push notifications must be additionally encrypted.
		**/
		public DeviceTokenFirebaseCloudMessaging(String token, boolean encrypt) {
			this.token = token;
			this.encrypt = encrypt;
		}

		/**
		 * A token for Firebase Cloud Messaging.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public DeviceTokenFirebaseCloudMessaging(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] tokenTmp = new byte[input.readInt()];
				input.readFully(tokenTmp);
				this.token = new String(tokenTmp, StandardCharsets.UTF_8);
			}
			this.encrypt = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return DeviceTokenFirebaseCloudMessaging.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(DeviceTokenFirebaseCloudMessaging.CONSTRUCTOR);
			if (this.token == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] tokenTmp = this.token.getBytes(StandardCharsets.UTF_8);
				output.writeInt(tokenTmp.length);
				output.write(tokenTmp);
			}
			output.writeBoolean(this.encrypt);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			DeviceTokenFirebaseCloudMessaging deviceTokenFirebaseCloudMessaging = (DeviceTokenFirebaseCloudMessaging) o;
			if (this.token != deviceTokenFirebaseCloudMessaging.token) {
				return false;
			}
			if (this.encrypt != deviceTokenFirebaseCloudMessaging.encrypt) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.encrypt);
			result = result * 31 + (this.token == null ? 0 : this.token.hashCode());
			return result;
		}
	}

	/**
	 * A token for Apple Push Notification service.
	**/
	public static final class DeviceTokenApplePush extends DeviceToken {


		/**
		 * Device token; may be empty to deregister a device.
		**/
		public String deviceToken;

		/**
		 * True, if App Sandbox is enabled.
		**/
		public boolean isAppSandbox;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 387541955;

		/**
		 * A token for Apple Push Notification service.
		**/
		public DeviceTokenApplePush() {}

		/**
		 * A token for Apple Push Notification service.
		 *
		 * @param deviceToken Device token; may be empty to deregister a device.
		 * @param isAppSandbox True, if App Sandbox is enabled.
		**/
		public DeviceTokenApplePush(String deviceToken, boolean isAppSandbox) {
			this.deviceToken = deviceToken;
			this.isAppSandbox = isAppSandbox;
		}

		/**
		 * A token for Apple Push Notification service.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public DeviceTokenApplePush(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] deviceTokenTmp = new byte[input.readInt()];
				input.readFully(deviceTokenTmp);
				this.deviceToken = new String(deviceTokenTmp, StandardCharsets.UTF_8);
			}
			this.isAppSandbox = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return DeviceTokenApplePush.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(DeviceTokenApplePush.CONSTRUCTOR);
			if (this.deviceToken == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] deviceTokenTmp = this.deviceToken.getBytes(StandardCharsets.UTF_8);
				output.writeInt(deviceTokenTmp.length);
				output.write(deviceTokenTmp);
			}
			output.writeBoolean(this.isAppSandbox);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			DeviceTokenApplePush deviceTokenApplePush = (DeviceTokenApplePush) o;
			if (this.deviceToken != deviceTokenApplePush.deviceToken) {
				return false;
			}
			if (this.isAppSandbox != deviceTokenApplePush.isAppSandbox) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isAppSandbox);
			result = result * 31 + (this.deviceToken == null ? 0 : this.deviceToken.hashCode());
			return result;
		}
	}

	/**
	 * A token for Apple Push Notification service VoIP notifications.
	**/
	public static final class DeviceTokenApplePushVoIP extends DeviceToken {


		/**
		 * Device token; may be empty to deregister a device.
		**/
		public String deviceToken;

		/**
		 * True, if App Sandbox is enabled.
		**/
		public boolean isAppSandbox;

		/**
		 * True, if push notifications must be additionally encrypted.
		**/
		public boolean encrypt;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 804275689;

		/**
		 * A token for Apple Push Notification service VoIP notifications.
		**/
		public DeviceTokenApplePushVoIP() {}

		/**
		 * A token for Apple Push Notification service VoIP notifications.
		 *
		 * @param deviceToken Device token; may be empty to deregister a device.
		 * @param isAppSandbox True, if App Sandbox is enabled.
		 * @param encrypt True, if push notifications must be additionally encrypted.
		**/
		public DeviceTokenApplePushVoIP(String deviceToken, boolean isAppSandbox, boolean encrypt) {
			this.deviceToken = deviceToken;
			this.isAppSandbox = isAppSandbox;
			this.encrypt = encrypt;
		}

		/**
		 * A token for Apple Push Notification service VoIP notifications.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public DeviceTokenApplePushVoIP(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] deviceTokenTmp = new byte[input.readInt()];
				input.readFully(deviceTokenTmp);
				this.deviceToken = new String(deviceTokenTmp, StandardCharsets.UTF_8);
			}
			this.isAppSandbox = input.readBoolean();
			this.encrypt = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return DeviceTokenApplePushVoIP.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(DeviceTokenApplePushVoIP.CONSTRUCTOR);
			if (this.deviceToken == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] deviceTokenTmp = this.deviceToken.getBytes(StandardCharsets.UTF_8);
				output.writeInt(deviceTokenTmp.length);
				output.write(deviceTokenTmp);
			}
			output.writeBoolean(this.isAppSandbox);
			output.writeBoolean(this.encrypt);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			DeviceTokenApplePushVoIP deviceTokenApplePushVoIP = (DeviceTokenApplePushVoIP) o;
			if (this.deviceToken != deviceTokenApplePushVoIP.deviceToken) {
				return false;
			}
			if (this.isAppSandbox != deviceTokenApplePushVoIP.isAppSandbox) {
				return false;
			}
			if (this.encrypt != deviceTokenApplePushVoIP.encrypt) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isAppSandbox);
			result = result * 31 + (this.deviceToken == null ? 0 : this.deviceToken.hashCode());
			return result;
		}
	}

	/**
	 * A token for Windows Push Notification Services.
	**/
	public static final class DeviceTokenWindowsPush extends DeviceToken {


		/**
		 * The access token that will be used to send notifications; may be empty to deregister a device.
		**/
		public String accessToken;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1410514289;

		/**
		 * A token for Windows Push Notification Services.
		**/
		public DeviceTokenWindowsPush() {}

		/**
		 * A token for Windows Push Notification Services.
		 *
		 * @param accessToken The access token that will be used to send notifications; may be empty to deregister a device.
		**/
		public DeviceTokenWindowsPush(String accessToken) {
			this.accessToken = accessToken;
		}

		/**
		 * A token for Windows Push Notification Services.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public DeviceTokenWindowsPush(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] accessTokenTmp = new byte[input.readInt()];
				input.readFully(accessTokenTmp);
				this.accessToken = new String(accessTokenTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return DeviceTokenWindowsPush.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(DeviceTokenWindowsPush.CONSTRUCTOR);
			if (this.accessToken == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] accessTokenTmp = this.accessToken.getBytes(StandardCharsets.UTF_8);
				output.writeInt(accessTokenTmp.length);
				output.write(accessTokenTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			DeviceTokenWindowsPush deviceTokenWindowsPush = (DeviceTokenWindowsPush) o;
			if (this.accessToken != deviceTokenWindowsPush.accessToken) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.accessToken == null ? 0 : this.accessToken.hashCode();
		}
	}

	/**
	 * A token for Microsoft Push Notification Service.
	**/
	public static final class DeviceTokenMicrosoftPush extends DeviceToken {


		/**
		 * Push notification channel URI; may be empty to deregister a device.
		**/
		public String channelUri;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1224269900;

		/**
		 * A token for Microsoft Push Notification Service.
		**/
		public DeviceTokenMicrosoftPush() {}

		/**
		 * A token for Microsoft Push Notification Service.
		 *
		 * @param channelUri Push notification channel URI; may be empty to deregister a device.
		**/
		public DeviceTokenMicrosoftPush(String channelUri) {
			this.channelUri = channelUri;
		}

		/**
		 * A token for Microsoft Push Notification Service.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public DeviceTokenMicrosoftPush(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] channelUriTmp = new byte[input.readInt()];
				input.readFully(channelUriTmp);
				this.channelUri = new String(channelUriTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return DeviceTokenMicrosoftPush.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(DeviceTokenMicrosoftPush.CONSTRUCTOR);
			if (this.channelUri == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] channelUriTmp = this.channelUri.getBytes(StandardCharsets.UTF_8);
				output.writeInt(channelUriTmp.length);
				output.write(channelUriTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			DeviceTokenMicrosoftPush deviceTokenMicrosoftPush = (DeviceTokenMicrosoftPush) o;
			if (this.channelUri != deviceTokenMicrosoftPush.channelUri) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.channelUri == null ? 0 : this.channelUri.hashCode();
		}
	}

	/**
	 * A token for Microsoft Push Notification Service VoIP channel.
	**/
	public static final class DeviceTokenMicrosoftPushVoIP extends DeviceToken {


		/**
		 * Push notification channel URI; may be empty to deregister a device.
		**/
		public String channelUri;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -785603759;

		/**
		 * A token for Microsoft Push Notification Service VoIP channel.
		**/
		public DeviceTokenMicrosoftPushVoIP() {}

		/**
		 * A token for Microsoft Push Notification Service VoIP channel.
		 *
		 * @param channelUri Push notification channel URI; may be empty to deregister a device.
		**/
		public DeviceTokenMicrosoftPushVoIP(String channelUri) {
			this.channelUri = channelUri;
		}

		/**
		 * A token for Microsoft Push Notification Service VoIP channel.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public DeviceTokenMicrosoftPushVoIP(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] channelUriTmp = new byte[input.readInt()];
				input.readFully(channelUriTmp);
				this.channelUri = new String(channelUriTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return DeviceTokenMicrosoftPushVoIP.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(DeviceTokenMicrosoftPushVoIP.CONSTRUCTOR);
			if (this.channelUri == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] channelUriTmp = this.channelUri.getBytes(StandardCharsets.UTF_8);
				output.writeInt(channelUriTmp.length);
				output.write(channelUriTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			DeviceTokenMicrosoftPushVoIP deviceTokenMicrosoftPushVoIP = (DeviceTokenMicrosoftPushVoIP) o;
			if (this.channelUri != deviceTokenMicrosoftPushVoIP.channelUri) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.channelUri == null ? 0 : this.channelUri.hashCode();
		}
	}

	/**
	 * A token for web Push API.
	**/
	public static final class DeviceTokenWebPush extends DeviceToken {


		/**
		 * Absolute URL exposed by the push service where the application server can send push messages; may be empty to deregister a device.
		**/
		public String endpoint;

		/**
		 * Base64url-encoded P-256 elliptic curve Diffie-Hellman public key.
		**/
		public String p256dhBase64url;

		/**
		 * Base64url-encoded authentication secret.
		**/
		public String authBase64url;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1694507273;

		/**
		 * A token for web Push API.
		**/
		public DeviceTokenWebPush() {}

		/**
		 * A token for web Push API.
		 *
		 * @param endpoint Absolute URL exposed by the push service where the application server can send push messages; may be empty to deregister a device.
		 * @param p256dhBase64url Base64url-encoded P-256 elliptic curve Diffie-Hellman public key.
		 * @param authBase64url Base64url-encoded authentication secret.
		**/
		public DeviceTokenWebPush(String endpoint,
				String p256dhBase64url,
				String authBase64url) {
			this.endpoint = endpoint;
			this.p256dhBase64url = p256dhBase64url;
			this.authBase64url = authBase64url;
		}

		/**
		 * A token for web Push API.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public DeviceTokenWebPush(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] endpointTmp = new byte[input.readInt()];
				input.readFully(endpointTmp);
				this.endpoint = new String(endpointTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] p256dhBase64urlTmp = new byte[input.readInt()];
				input.readFully(p256dhBase64urlTmp);
				this.p256dhBase64url = new String(p256dhBase64urlTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] authBase64urlTmp = new byte[input.readInt()];
				input.readFully(authBase64urlTmp);
				this.authBase64url = new String(authBase64urlTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return DeviceTokenWebPush.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(DeviceTokenWebPush.CONSTRUCTOR);
			if (this.endpoint == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] endpointTmp = this.endpoint.getBytes(StandardCharsets.UTF_8);
				output.writeInt(endpointTmp.length);
				output.write(endpointTmp);
			}
			if (this.p256dhBase64url == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] p256dhBase64urlTmp = this.p256dhBase64url.getBytes(StandardCharsets.UTF_8);
				output.writeInt(p256dhBase64urlTmp.length);
				output.write(p256dhBase64urlTmp);
			}
			if (this.authBase64url == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] authBase64urlTmp = this.authBase64url.getBytes(StandardCharsets.UTF_8);
				output.writeInt(authBase64urlTmp.length);
				output.write(authBase64urlTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			DeviceTokenWebPush deviceTokenWebPush = (DeviceTokenWebPush) o;
			if (this.endpoint != deviceTokenWebPush.endpoint) {
				return false;
			}
			if (this.p256dhBase64url != deviceTokenWebPush.p256dhBase64url) {
				return false;
			}
			if (this.authBase64url != deviceTokenWebPush.authBase64url) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.endpoint == null ? 0 : this.endpoint.hashCode();
			result = result * 31 + (this.p256dhBase64url == null ? 0 : this.p256dhBase64url.hashCode());
			result = result * 31 + (this.authBase64url == null ? 0 : this.authBase64url.hashCode());
			return result;
		}
	}

	/**
	 * A token for Simple Push API for Firefox OS.
	**/
	public static final class DeviceTokenSimplePush extends DeviceToken {


		/**
		 * Absolute URL exposed by the push service where the application server can send push messages; may be empty to deregister a device.
		**/
		public String endpoint;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 49584736;

		/**
		 * A token for Simple Push API for Firefox OS.
		**/
		public DeviceTokenSimplePush() {}

		/**
		 * A token for Simple Push API for Firefox OS.
		 *
		 * @param endpoint Absolute URL exposed by the push service where the application server can send push messages; may be empty to deregister a device.
		**/
		public DeviceTokenSimplePush(String endpoint) {
			this.endpoint = endpoint;
		}

		/**
		 * A token for Simple Push API for Firefox OS.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public DeviceTokenSimplePush(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] endpointTmp = new byte[input.readInt()];
				input.readFully(endpointTmp);
				this.endpoint = new String(endpointTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return DeviceTokenSimplePush.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(DeviceTokenSimplePush.CONSTRUCTOR);
			if (this.endpoint == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] endpointTmp = this.endpoint.getBytes(StandardCharsets.UTF_8);
				output.writeInt(endpointTmp.length);
				output.write(endpointTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			DeviceTokenSimplePush deviceTokenSimplePush = (DeviceTokenSimplePush) o;
			if (this.endpoint != deviceTokenSimplePush.endpoint) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.endpoint == null ? 0 : this.endpoint.hashCode();
		}
	}

	/**
	 * A token for Ubuntu Push Client service.
	**/
	public static final class DeviceTokenUbuntuPush extends DeviceToken {


		/**
		 * Token; may be empty to deregister a device.
		**/
		public String token;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1782320422;

		/**
		 * A token for Ubuntu Push Client service.
		**/
		public DeviceTokenUbuntuPush() {}

		/**
		 * A token for Ubuntu Push Client service.
		 *
		 * @param token Token; may be empty to deregister a device.
		**/
		public DeviceTokenUbuntuPush(String token) {
			this.token = token;
		}

		/**
		 * A token for Ubuntu Push Client service.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public DeviceTokenUbuntuPush(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] tokenTmp = new byte[input.readInt()];
				input.readFully(tokenTmp);
				this.token = new String(tokenTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return DeviceTokenUbuntuPush.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(DeviceTokenUbuntuPush.CONSTRUCTOR);
			if (this.token == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] tokenTmp = this.token.getBytes(StandardCharsets.UTF_8);
				output.writeInt(tokenTmp.length);
				output.write(tokenTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			DeviceTokenUbuntuPush deviceTokenUbuntuPush = (DeviceTokenUbuntuPush) o;
			if (this.token != deviceTokenUbuntuPush.token) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.token == null ? 0 : this.token.hashCode();
		}
	}

	/**
	 * A token for BlackBerry Push Service.
	**/
	public static final class DeviceTokenBlackBerryPush extends DeviceToken {


		/**
		 * Token; may be empty to deregister a device.
		**/
		public String token;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1559167234;

		/**
		 * A token for BlackBerry Push Service.
		**/
		public DeviceTokenBlackBerryPush() {}

		/**
		 * A token for BlackBerry Push Service.
		 *
		 * @param token Token; may be empty to deregister a device.
		**/
		public DeviceTokenBlackBerryPush(String token) {
			this.token = token;
		}

		/**
		 * A token for BlackBerry Push Service.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public DeviceTokenBlackBerryPush(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] tokenTmp = new byte[input.readInt()];
				input.readFully(tokenTmp);
				this.token = new String(tokenTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return DeviceTokenBlackBerryPush.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(DeviceTokenBlackBerryPush.CONSTRUCTOR);
			if (this.token == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] tokenTmp = this.token.getBytes(StandardCharsets.UTF_8);
				output.writeInt(tokenTmp.length);
				output.write(tokenTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			DeviceTokenBlackBerryPush deviceTokenBlackBerryPush = (DeviceTokenBlackBerryPush) o;
			if (this.token != deviceTokenBlackBerryPush.token) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.token == null ? 0 : this.token.hashCode();
		}
	}

	/**
	 * A token for Tizen Push Service.
	**/
	public static final class DeviceTokenTizenPush extends DeviceToken {


		/**
		 * Push service registration identifier; may be empty to deregister a device.
		**/
		public String regId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1359947213;

		/**
		 * A token for Tizen Push Service.
		**/
		public DeviceTokenTizenPush() {}

		/**
		 * A token for Tizen Push Service.
		 *
		 * @param regId Push service registration identifier; may be empty to deregister a device.
		**/
		public DeviceTokenTizenPush(String regId) {
			this.regId = regId;
		}

		/**
		 * A token for Tizen Push Service.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public DeviceTokenTizenPush(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] regIdTmp = new byte[input.readInt()];
				input.readFully(regIdTmp);
				this.regId = new String(regIdTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return DeviceTokenTizenPush.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(DeviceTokenTizenPush.CONSTRUCTOR);
			if (this.regId == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] regIdTmp = this.regId.getBytes(StandardCharsets.UTF_8);
				output.writeInt(regIdTmp.length);
				output.write(regIdTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			DeviceTokenTizenPush deviceTokenTizenPush = (DeviceTokenTizenPush) o;
			if (this.regId != deviceTokenTizenPush.regId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.regId == null ? 0 : this.regId.hashCode();
		}
	}

	/**
	 * A token for HUAWEI Push Service.
	**/
	public static final class DeviceTokenHuaweiPush extends DeviceToken {


		/**
		 * Device registration token; may be empty to deregister a device.
		**/
		public String token;

		/**
		 * True, if push notifications must be additionally encrypted.
		**/
		public boolean encrypt;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1989103142;

		/**
		 * A token for HUAWEI Push Service.
		**/
		public DeviceTokenHuaweiPush() {}

		/**
		 * A token for HUAWEI Push Service.
		 *
		 * @param token Device registration token; may be empty to deregister a device.
		 * @param encrypt True, if push notifications must be additionally encrypted.
		**/
		public DeviceTokenHuaweiPush(String token, boolean encrypt) {
			this.token = token;
			this.encrypt = encrypt;
		}

		/**
		 * A token for HUAWEI Push Service.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public DeviceTokenHuaweiPush(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] tokenTmp = new byte[input.readInt()];
				input.readFully(tokenTmp);
				this.token = new String(tokenTmp, StandardCharsets.UTF_8);
			}
			this.encrypt = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return DeviceTokenHuaweiPush.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(DeviceTokenHuaweiPush.CONSTRUCTOR);
			if (this.token == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] tokenTmp = this.token.getBytes(StandardCharsets.UTF_8);
				output.writeInt(tokenTmp.length);
				output.write(tokenTmp);
			}
			output.writeBoolean(this.encrypt);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			DeviceTokenHuaweiPush deviceTokenHuaweiPush = (DeviceTokenHuaweiPush) o;
			if (this.token != deviceTokenHuaweiPush.token) {
				return false;
			}
			if (this.encrypt != deviceTokenHuaweiPush.encrypt) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.encrypt);
			result = result * 31 + (this.token == null ? 0 : this.token.hashCode());
			return result;
		}
	}

	/**
	 * A regular animated sticker.
	**/
	public static final class DiceStickersRegular extends DiceStickers {


		/**
		 * The animated sticker with the dice animation.
		**/
		public Sticker sticker;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -740299570;

		/**
		 * A regular animated sticker.
		**/
		public DiceStickersRegular() {}

		/**
		 * A regular animated sticker.
		 *
		 * @param sticker The animated sticker with the dice animation.
		**/
		public DiceStickersRegular(Sticker sticker) {
			this.sticker = sticker;
		}

		/**
		 * A regular animated sticker.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public DiceStickersRegular(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Sticker.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.sticker = new Sticker(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return DiceStickersRegular.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(DiceStickersRegular.CONSTRUCTOR);
			if (this.sticker == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.sticker.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			DiceStickersRegular diceStickersRegular = (DiceStickersRegular) o;
			if (!Objects.equals(this.sticker, diceStickersRegular.sticker)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.sticker == null ? 0 : this.sticker.hashCode();
		}
	}

	/**
	 * Animated stickers to be combined into a slot machine.
	**/
	public static final class DiceStickersSlotMachine extends DiceStickers {


		/**
		 * The animated sticker with the slot machine background. The background animation must start playing after all reel animations finish.
		**/
		public Sticker background;

		/**
		 * The animated sticker with the lever animation. The lever animation must play once in the initial dice state.
		**/
		public Sticker lever;

		/**
		 * The animated sticker with the left reel.
		**/
		public Sticker leftReel;

		/**
		 * The animated sticker with the center reel.
		**/
		public Sticker centerReel;

		/**
		 * The animated sticker with the right reel.
		**/
		public Sticker rightReel;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -375223124;

		/**
		 * Animated stickers to be combined into a slot machine.
		**/
		public DiceStickersSlotMachine() {}

		/**
		 * Animated stickers to be combined into a slot machine.
		 *
		 * @param background The animated sticker with the slot machine background. The background animation must start playing after all reel animations finish.
		 * @param lever The animated sticker with the lever animation. The lever animation must play once in the initial dice state.
		 * @param leftReel The animated sticker with the left reel.
		 * @param centerReel The animated sticker with the center reel.
		 * @param rightReel The animated sticker with the right reel.
		**/
		public DiceStickersSlotMachine(Sticker background,
				Sticker lever,
				Sticker leftReel,
				Sticker centerReel,
				Sticker rightReel) {
			this.background = background;
			this.lever = lever;
			this.leftReel = leftReel;
			this.centerReel = centerReel;
			this.rightReel = rightReel;
		}

		/**
		 * Animated stickers to be combined into a slot machine.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public DiceStickersSlotMachine(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Sticker.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.background = new Sticker(input);
			}
			if (input.readBoolean()) {
				if (Sticker.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.lever = new Sticker(input);
			}
			if (input.readBoolean()) {
				if (Sticker.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.leftReel = new Sticker(input);
			}
			if (input.readBoolean()) {
				if (Sticker.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.centerReel = new Sticker(input);
			}
			if (input.readBoolean()) {
				if (Sticker.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.rightReel = new Sticker(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return DiceStickersSlotMachine.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(DiceStickersSlotMachine.CONSTRUCTOR);
			if (this.background == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.background.serialize(output);
			}
			if (this.lever == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.lever.serialize(output);
			}
			if (this.leftReel == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.leftReel.serialize(output);
			}
			if (this.centerReel == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.centerReel.serialize(output);
			}
			if (this.rightReel == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.rightReel.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			DiceStickersSlotMachine diceStickersSlotMachine = (DiceStickersSlotMachine) o;
			if (!Objects.equals(this.background, diceStickersSlotMachine.background)) {
				return false;
			}
			if (!Objects.equals(this.lever, diceStickersSlotMachine.lever)) {
				return false;
			}
			if (!Objects.equals(this.leftReel, diceStickersSlotMachine.leftReel)) {
				return false;
			}
			if (!Objects.equals(this.centerReel, diceStickersSlotMachine.centerReel)) {
				return false;
			}
			if (!Objects.equals(this.rightReel, diceStickersSlotMachine.rightReel)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.background == null ? 0 : this.background.hashCode();
			result = result * 31 + (this.lever == null ? 0 : this.lever.hashCode());
			result = result * 31 + (this.leftReel == null ? 0 : this.leftReel.hashCode());
			result = result * 31 + (this.centerReel == null ? 0 : this.centerReel.hashCode());
			result = result * 31 + (this.rightReel == null ? 0 : this.rightReel.hashCode());
			return result;
		}
	}

	/**
	 * Describes a document of any type.
	**/
	public static final class Document extends Object {


		/**
		 * Original name of the file; as defined by the sender.
		**/
		public String fileName;

		/**
		 * MIME type of the file; as defined by the sender.
		**/
		public String mimeType;

		/**
		 * Document minithumbnail; may be null.
		**/
		public Minithumbnail minithumbnail;

		/**
		 * Document thumbnail in JPEG or PNG format (PNG will be used only for background patterns); as defined by the sender; may be null.
		**/
		public Thumbnail thumbnail;

		/**
		 * File containing the document.
		**/
		public File document;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1357271080;

		/**
		 * Describes a document of any type.
		**/
		public Document() {}

		/**
		 * Describes a document of any type.
		 *
		 * @param fileName Original name of the file; as defined by the sender.
		 * @param mimeType MIME type of the file; as defined by the sender.
		 * @param minithumbnail Document minithumbnail; may be null.
		 * @param thumbnail Document thumbnail in JPEG or PNG format (PNG will be used only for background patterns); as defined by the sender; may be null.
		 * @param document File containing the document.
		**/
		public Document(String fileName,
				String mimeType,
				Minithumbnail minithumbnail,
				Thumbnail thumbnail,
				File document) {
			this.fileName = fileName;
			this.mimeType = mimeType;
			this.minithumbnail = minithumbnail;
			this.thumbnail = thumbnail;
			this.document = document;
		}

		/**
		 * Describes a document of any type.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public Document(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] fileNameTmp = new byte[input.readInt()];
				input.readFully(fileNameTmp);
				this.fileName = new String(fileNameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] mimeTypeTmp = new byte[input.readInt()];
				input.readFully(mimeTypeTmp);
				this.mimeType = new String(mimeTypeTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (Minithumbnail.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.minithumbnail = new Minithumbnail(input);
			}
			if (input.readBoolean()) {
				if (Thumbnail.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.thumbnail = new Thumbnail(input);
			}
			if (input.readBoolean()) {
				if (File.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.document = new File(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return Document.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(Document.CONSTRUCTOR);
			if (this.fileName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] fileNameTmp = this.fileName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(fileNameTmp.length);
				output.write(fileNameTmp);
			}
			if (this.mimeType == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] mimeTypeTmp = this.mimeType.getBytes(StandardCharsets.UTF_8);
				output.writeInt(mimeTypeTmp.length);
				output.write(mimeTypeTmp);
			}
			if (this.minithumbnail == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.minithumbnail.serialize(output);
			}
			if (this.thumbnail == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.thumbnail.serialize(output);
			}
			if (this.document == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.document.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			Document document = (Document) o;
			if (this.fileName != document.fileName) {
				return false;
			}
			if (this.mimeType != document.mimeType) {
				return false;
			}
			if (!Objects.equals(this.minithumbnail, document.minithumbnail)) {
				return false;
			}
			if (!Objects.equals(this.thumbnail, document.thumbnail)) {
				return false;
			}
			if (!Objects.equals(this.document, document.document)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.fileName == null ? 0 : this.fileName.hashCode();
			result = result * 31 + (this.mimeType == null ? 0 : this.mimeType.hashCode());
			result = result * 31 + (this.minithumbnail == null ? 0 : this.minithumbnail.hashCode());
			result = result * 31 + (this.thumbnail == null ? 0 : this.thumbnail.hashCode());
			result = result * 31 + (this.document == null ? 0 : this.document.hashCode());
			return result;
		}
	}

	/**
	 * Contains number of being downloaded and recently downloaded files
	 * found.
	**/
	public static final class DownloadedFileCounts extends Object {


		/**
		 * Number of active file downloads found, including paused.
		**/
		public int activeCount;

		/**
		 * Number of paused file downloads found.
		**/
		public int pausedCount;

		/**
		 * Number of completed file downloads found.
		**/
		public int completedCount;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1973999550;

		/**
		 * Contains number of being downloaded and recently downloaded files found.
		**/
		public DownloadedFileCounts() {}

		/**
		 * Contains number of being downloaded and recently downloaded files found.
		 *
		 * @param activeCount Number of active file downloads found, including paused.
		 * @param pausedCount Number of paused file downloads found.
		 * @param completedCount Number of completed file downloads found.
		**/
		public DownloadedFileCounts(int activeCount, int pausedCount, int completedCount) {
			this.activeCount = activeCount;
			this.pausedCount = pausedCount;
			this.completedCount = completedCount;
		}

		/**
		 * Contains number of being downloaded and recently downloaded files found.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public DownloadedFileCounts(DataInput input) throws IOException {
			this.activeCount = input.readInt();
			this.pausedCount = input.readInt();
			this.completedCount = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return DownloadedFileCounts.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(DownloadedFileCounts.CONSTRUCTOR);
			output.writeInt(this.activeCount);
			output.writeInt(this.pausedCount);
			output.writeInt(this.completedCount);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			DownloadedFileCounts downloadedFileCounts = (DownloadedFileCounts) o;
			if (this.activeCount != downloadedFileCounts.activeCount) {
				return false;
			}
			if (this.pausedCount != downloadedFileCounts.pausedCount) {
				return false;
			}
			if (this.completedCount != downloadedFileCounts.completedCount) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.activeCount);
			return result;
		}
	}

	/**
	 * Contains information about a message draft.
	**/
	public static final class DraftMessage extends Object {


		/**
		 * Identifier of the replied message; 0 if none.
		**/
		public long replyToMessageId;

		/**
		 * Point in time (Unix timestamp) when the draft was created.
		**/
		public int date;

		/**
		 * Content of the message draft; must be of the type inputMessageText.
		**/
		public InputMessageContent inputMessageText;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1373050112;

		/**
		 * Contains information about a message draft.
		**/
		public DraftMessage() {}

		/**
		 * Contains information about a message draft.
		 *
		 * @param replyToMessageId Identifier of the replied message; 0 if none.
		 * @param date Point in time (Unix timestamp) when the draft was created.
		 * @param inputMessageText Content of the message draft; must be of the type inputMessageText.
		**/
		public DraftMessage(long replyToMessageId,
				int date,
				InputMessageContent inputMessageText) {
			this.replyToMessageId = replyToMessageId;
			this.date = date;
			this.inputMessageText = inputMessageText;
		}

		/**
		 * Contains information about a message draft.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public DraftMessage(DataInput input) throws IOException {
			this.replyToMessageId = input.readLong();
			this.date = input.readInt();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputMessageText.CONSTRUCTOR: this.inputMessageText = new InputMessageText(input); break;
					case InputMessageAnimation.CONSTRUCTOR: this.inputMessageText = new InputMessageAnimation(input); break;
					case InputMessageAudio.CONSTRUCTOR: this.inputMessageText = new InputMessageAudio(input); break;
					case InputMessageDocument.CONSTRUCTOR: this.inputMessageText = new InputMessageDocument(input); break;
					case InputMessagePhoto.CONSTRUCTOR: this.inputMessageText = new InputMessagePhoto(input); break;
					case InputMessageSticker.CONSTRUCTOR: this.inputMessageText = new InputMessageSticker(input); break;
					case InputMessageVideo.CONSTRUCTOR: this.inputMessageText = new InputMessageVideo(input); break;
					case InputMessageVideoNote.CONSTRUCTOR: this.inputMessageText = new InputMessageVideoNote(input); break;
					case InputMessageVoiceNote.CONSTRUCTOR: this.inputMessageText = new InputMessageVoiceNote(input); break;
					case InputMessageLocation.CONSTRUCTOR: this.inputMessageText = new InputMessageLocation(input); break;
					case InputMessageVenue.CONSTRUCTOR: this.inputMessageText = new InputMessageVenue(input); break;
					case InputMessageContact.CONSTRUCTOR: this.inputMessageText = new InputMessageContact(input); break;
					case InputMessageDice.CONSTRUCTOR: this.inputMessageText = new InputMessageDice(input); break;
					case InputMessageGame.CONSTRUCTOR: this.inputMessageText = new InputMessageGame(input); break;
					case InputMessageInvoice.CONSTRUCTOR: this.inputMessageText = new InputMessageInvoice(input); break;
					case InputMessagePoll.CONSTRUCTOR: this.inputMessageText = new InputMessagePoll(input); break;
					case InputMessageForwarded.CONSTRUCTOR: this.inputMessageText = new InputMessageForwarded(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return DraftMessage.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(DraftMessage.CONSTRUCTOR);
			output.writeLong(this.replyToMessageId);
			output.writeInt(this.date);
			if (this.inputMessageText == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.inputMessageText.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			DraftMessage draftMessage = (DraftMessage) o;
			if (this.replyToMessageId != draftMessage.replyToMessageId) {
				return false;
			}
			if (this.date != draftMessage.date) {
				return false;
			}
			if (!Objects.equals(this.inputMessageText, draftMessage.inputMessageText)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.replyToMessageId);
			result = result * 31 + (this.inputMessageText == null ? 0 : this.inputMessageText.hashCode());
			return result;
		}
	}

	/**
	 * An authentication code delivered to a user&#039;s email address.
	**/
	public static final class EmailAddressAuthenticationCode extends EmailAddressAuthentication {


		/**
		 * The code.
		**/
		public String code;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -993257022;

		/**
		 * An authentication code delivered to a user&#039;s email address.
		**/
		public EmailAddressAuthenticationCode() {}

		/**
		 * An authentication code delivered to a user&#039;s email address.
		 *
		 * @param code The code.
		**/
		public EmailAddressAuthenticationCode(String code) {
			this.code = code;
		}

		/**
		 * An authentication code delivered to a user&#039;s email address.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public EmailAddressAuthenticationCode(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] codeTmp = new byte[input.readInt()];
				input.readFully(codeTmp);
				this.code = new String(codeTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return EmailAddressAuthenticationCode.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(EmailAddressAuthenticationCode.CONSTRUCTOR);
			if (this.code == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] codeTmp = this.code.getBytes(StandardCharsets.UTF_8);
				output.writeInt(codeTmp.length);
				output.write(codeTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			EmailAddressAuthenticationCode emailAddressAuthenticationCode = (EmailAddressAuthenticationCode) o;
			if (this.code != emailAddressAuthenticationCode.code) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.code == null ? 0 : this.code.hashCode();
		}
	}

	/**
	 * An authentication token received through Apple ID.
	**/
	public static final class EmailAddressAuthenticationAppleId extends EmailAddressAuthentication {


		/**
		 * The token.
		**/
		public String token;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 633948265;

		/**
		 * An authentication token received through Apple ID.
		**/
		public EmailAddressAuthenticationAppleId() {}

		/**
		 * An authentication token received through Apple ID.
		 *
		 * @param token The token.
		**/
		public EmailAddressAuthenticationAppleId(String token) {
			this.token = token;
		}

		/**
		 * An authentication token received through Apple ID.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public EmailAddressAuthenticationAppleId(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] tokenTmp = new byte[input.readInt()];
				input.readFully(tokenTmp);
				this.token = new String(tokenTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return EmailAddressAuthenticationAppleId.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(EmailAddressAuthenticationAppleId.CONSTRUCTOR);
			if (this.token == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] tokenTmp = this.token.getBytes(StandardCharsets.UTF_8);
				output.writeInt(tokenTmp.length);
				output.write(tokenTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			EmailAddressAuthenticationAppleId emailAddressAuthenticationAppleId = (EmailAddressAuthenticationAppleId) o;
			if (this.token != emailAddressAuthenticationAppleId.token) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.token == null ? 0 : this.token.hashCode();
		}
	}

	/**
	 * An authentication token received through Google ID.
	**/
	public static final class EmailAddressAuthenticationGoogleId extends EmailAddressAuthentication {


		/**
		 * The token.
		**/
		public String token;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -19142846;

		/**
		 * An authentication token received through Google ID.
		**/
		public EmailAddressAuthenticationGoogleId() {}

		/**
		 * An authentication token received through Google ID.
		 *
		 * @param token The token.
		**/
		public EmailAddressAuthenticationGoogleId(String token) {
			this.token = token;
		}

		/**
		 * An authentication token received through Google ID.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public EmailAddressAuthenticationGoogleId(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] tokenTmp = new byte[input.readInt()];
				input.readFully(tokenTmp);
				this.token = new String(tokenTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return EmailAddressAuthenticationGoogleId.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(EmailAddressAuthenticationGoogleId.CONSTRUCTOR);
			if (this.token == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] tokenTmp = this.token.getBytes(StandardCharsets.UTF_8);
				output.writeInt(tokenTmp.length);
				output.write(tokenTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			EmailAddressAuthenticationGoogleId emailAddressAuthenticationGoogleId = (EmailAddressAuthenticationGoogleId) o;
			if (this.token != emailAddressAuthenticationGoogleId.token) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.token == null ? 0 : this.token.hashCode();
		}
	}

	/**
	 * Information about the email address authentication code that was sent.
	**/
	public static final class EmailAddressAuthenticationCodeInfo extends Object {


		/**
		 * Pattern of the email address to which an authentication code was sent.
		**/
		public String emailAddressPattern;

		/**
		 * Length of the code; 0 if unknown.
		**/
		public int length;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1151066659;

		/**
		 * Information about the email address authentication code that was sent.
		**/
		public EmailAddressAuthenticationCodeInfo() {}

		/**
		 * Information about the email address authentication code that was sent.
		 *
		 * @param emailAddressPattern Pattern of the email address to which an authentication code was sent.
		 * @param length Length of the code; 0 if unknown.
		**/
		public EmailAddressAuthenticationCodeInfo(String emailAddressPattern, int length) {
			this.emailAddressPattern = emailAddressPattern;
			this.length = length;
		}

		/**
		 * Information about the email address authentication code that was sent.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public EmailAddressAuthenticationCodeInfo(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] emailAddressPatternTmp = new byte[input.readInt()];
				input.readFully(emailAddressPatternTmp);
				this.emailAddressPattern = new String(emailAddressPatternTmp, StandardCharsets.UTF_8);
			}
			this.length = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return EmailAddressAuthenticationCodeInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(EmailAddressAuthenticationCodeInfo.CONSTRUCTOR);
			if (this.emailAddressPattern == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] emailAddressPatternTmp = this.emailAddressPattern.getBytes(StandardCharsets.UTF_8);
				output.writeInt(emailAddressPatternTmp.length);
				output.write(emailAddressPatternTmp);
			}
			output.writeInt(this.length);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			EmailAddressAuthenticationCodeInfo emailAddressAuthenticationCodeInfo = (EmailAddressAuthenticationCodeInfo) o;
			if (this.emailAddressPattern != emailAddressAuthenticationCodeInfo.emailAddressPattern) {
				return false;
			}
			if (this.length != emailAddressAuthenticationCodeInfo.length) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.length);
			result = result * 31 + (this.emailAddressPattern == null ? 0 : this.emailAddressPattern.hashCode());
			return result;
		}
	}

	/**
	 * Email address can be reset after the given period. Call
	 * resetAuthenticationEmailAddress to reset it and allow the user to
	 * authorize with a code sent to the user&#039;s phone number.
	**/
	public static final class EmailAddressResetStateAvailable extends EmailAddressResetState {


		/**
		 * Time required to wait before the email address can be reset; 0 if the user is subscribed to Telegram Premium.
		**/
		public int waitPeriod;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1917177600;

		/**
		 * Email address can be reset after the given period. Call resetAuthenticationEmailAddress to reset it and allow the user to authorize with a code sent to the user&#039;s phone number.
		**/
		public EmailAddressResetStateAvailable() {}

		/**
		 * Email address can be reset after the given period. Call resetAuthenticationEmailAddress to reset it and allow the user to authorize with a code sent to the user&#039;s phone number.
		 *
		 * @param waitPeriod Time required to wait before the email address can be reset; 0 if the user is subscribed to Telegram Premium.
		**/
		public EmailAddressResetStateAvailable(int waitPeriod) {
			this.waitPeriod = waitPeriod;
		}

		/**
		 * Email address can be reset after the given period. Call resetAuthenticationEmailAddress to reset it and allow the user to authorize with a code sent to the user&#039;s phone number.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public EmailAddressResetStateAvailable(DataInput input) throws IOException {
			this.waitPeriod = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return EmailAddressResetStateAvailable.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(EmailAddressResetStateAvailable.CONSTRUCTOR);
			output.writeInt(this.waitPeriod);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			EmailAddressResetStateAvailable emailAddressResetStateAvailable = (EmailAddressResetStateAvailable) o;
			if (this.waitPeriod != emailAddressResetStateAvailable.waitPeriod) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.waitPeriod);
		}
	}

	/**
	 * Email address reset has already been requested. Call
	 * resetAuthenticationEmailAddress to check whether immediate reset is
	 * possible.
	**/
	public static final class EmailAddressResetStatePending extends EmailAddressResetState {


		/**
		 * Left time before the email address will be reset, in seconds. updateAuthorizationState is not sent when this field changes.
		**/
		public int resetIn;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1885966805;

		/**
		 * Email address reset has already been requested. Call resetAuthenticationEmailAddress to check whether immediate reset is possible.
		**/
		public EmailAddressResetStatePending() {}

		/**
		 * Email address reset has already been requested. Call resetAuthenticationEmailAddress to check whether immediate reset is possible.
		 *
		 * @param resetIn Left time before the email address will be reset, in seconds. updateAuthorizationState is not sent when this field changes.
		**/
		public EmailAddressResetStatePending(int resetIn) {
			this.resetIn = resetIn;
		}

		/**
		 * Email address reset has already been requested. Call resetAuthenticationEmailAddress to check whether immediate reset is possible.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public EmailAddressResetStatePending(DataInput input) throws IOException {
			this.resetIn = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return EmailAddressResetStatePending.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(EmailAddressResetStatePending.CONSTRUCTOR);
			output.writeInt(this.resetIn);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			EmailAddressResetStatePending emailAddressResetStatePending = (EmailAddressResetStatePending) o;
			if (this.resetIn != emailAddressResetStatePending.resetIn) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.resetIn);
		}
	}

	/**
	 * Represents a list of emoji categories.
	**/
	public static final class EmojiCategories extends Object {


		/**
		 * List of categories.
		**/
		public EmojiCategory[] categories;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1455387824;

		/**
		 * Represents a list of emoji categories.
		**/
		public EmojiCategories() {}

		/**
		 * Represents a list of emoji categories.
		 *
		 * @param categories List of categories.
		**/
		public EmojiCategories(EmojiCategory[] categories) {
			this.categories = categories;
		}

		/**
		 * Represents a list of emoji categories.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public EmojiCategories(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.categories = new EmojiCategory[input.readInt()];
				for (int i = 0; i < this.categories.length; i++) {
					if (EmojiCategory.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.categories[i] = new EmojiCategory(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return EmojiCategories.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(EmojiCategories.CONSTRUCTOR);
			if (this.categories == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.categories.length);
				for (int i = 0; i < this.categories.length; i++) {
					this.categories[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			EmojiCategories emojiCategories = (EmojiCategories) o;
			if (!Arrays.equals(this.categories, emojiCategories.categories)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.categories);
		}
	}

	/**
	 * Contains a list of similar emoji to search for in getStickers and
	 * searchStickers.
	**/
	public static final class EmojiCategory extends Object {


		/**
		 * Name of the category.
		**/
		public String name;

		/**
		 * Custom emoji sticker, which represents icon of the category.
		**/
		public Sticker icon;

		/**
		 * List of emojis in the category.
		**/
		public String[] emojis;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1019393600;

		/**
		 * Contains a list of similar emoji to search for in getStickers and searchStickers.
		**/
		public EmojiCategory() {}

		/**
		 * Contains a list of similar emoji to search for in getStickers and searchStickers.
		 *
		 * @param name Name of the category.
		 * @param icon Custom emoji sticker, which represents icon of the category.
		 * @param emojis List of emojis in the category.
		**/
		public EmojiCategory(String name, Sticker icon, String[] emojis) {
			this.name = name;
			this.icon = icon;
			this.emojis = emojis;
		}

		/**
		 * Contains a list of similar emoji to search for in getStickers and searchStickers.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public EmojiCategory(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] nameTmp = new byte[input.readInt()];
				input.readFully(nameTmp);
				this.name = new String(nameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (Sticker.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.icon = new Sticker(input);
			}
			if (input.readBoolean()) {
				this.emojis = new String[input.readInt()];
				for (int i = 0; i < this.emojis.length; i++) {
					byte[] emojisTmp = new byte[input.readInt()];
					input.readFully(emojisTmp);
					this.emojis[i] = new String(emojisTmp, StandardCharsets.UTF_8);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return EmojiCategory.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(EmojiCategory.CONSTRUCTOR);
			if (this.name == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nameTmp = this.name.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nameTmp.length);
				output.write(nameTmp);
			}
			if (this.icon == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.icon.serialize(output);
			}
			if (this.emojis == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.emojis.length);
				for (int i = 0; i < this.emojis.length; i++) {
					byte[] emojisTmp = this.emojis[i].getBytes(StandardCharsets.UTF_8);
					output.writeInt(emojisTmp.length);
					output.write(emojisTmp);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			EmojiCategory emojiCategory = (EmojiCategory) o;
			if (this.name != emojiCategory.name) {
				return false;
			}
			if (!Objects.equals(this.icon, emojiCategory.icon)) {
				return false;
			}
			if (!Arrays.equals(this.emojis, emojiCategory.emojis)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.name == null ? 0 : this.name.hashCode();
			result = result * 31 + (this.icon == null ? 0 : this.icon.hashCode());
			result = result * 31 + (Arrays.hashCode(this.emojis));
			return result;
		}
	}

	/**
	 * The category must be used by default.
	**/
	public static final class EmojiCategoryTypeDefault extends EmojiCategoryType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1188782699;

		/**
		 * The category must be used by default.
		**/
		public EmojiCategoryTypeDefault() {}

		/**
		 * The category must be used by default.
		 *
		**/

		/**
		 * The category must be used by default.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public EmojiCategoryTypeDefault(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return EmojiCategoryTypeDefault.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(EmojiCategoryTypeDefault.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return EmojiCategoryTypeDefault.CONSTRUCTOR;
		}
	}

	/**
	 * The category must be used for emoji status selection.
	**/
	public static final class EmojiCategoryTypeEmojiStatus extends EmojiCategoryType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1381282631;

		/**
		 * The category must be used for emoji status selection.
		**/
		public EmojiCategoryTypeEmojiStatus() {}

		/**
		 * The category must be used for emoji status selection.
		 *
		**/

		/**
		 * The category must be used for emoji status selection.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public EmojiCategoryTypeEmojiStatus(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return EmojiCategoryTypeEmojiStatus.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(EmojiCategoryTypeEmojiStatus.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return EmojiCategoryTypeEmojiStatus.CONSTRUCTOR;
		}
	}

	/**
	 * The category must be used for chat photo emoji selection.
	**/
	public static final class EmojiCategoryTypeChatPhoto extends EmojiCategoryType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1059063081;

		/**
		 * The category must be used for chat photo emoji selection.
		**/
		public EmojiCategoryTypeChatPhoto() {}

		/**
		 * The category must be used for chat photo emoji selection.
		 *
		**/

		/**
		 * The category must be used for chat photo emoji selection.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public EmojiCategoryTypeChatPhoto(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return EmojiCategoryTypeChatPhoto.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(EmojiCategoryTypeChatPhoto.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return EmojiCategoryTypeChatPhoto.CONSTRUCTOR;
		}
	}

	/**
	 * Contains information about a emoji reaction.
	**/
	public static final class EmojiReaction extends Object {


		/**
		 * Text representation of the reaction.
		**/
		public String emoji;

		/**
		 * Reaction title.
		**/
		public String title;

		/**
		 * True, if the reaction can be added to new messages and enabled in chats.
		**/
		public boolean isActive;

		/**
		 * Static icon for the reaction.
		**/
		public Sticker staticIcon;

		/**
		 * Appear animation for the reaction.
		**/
		public Sticker appearAnimation;

		/**
		 * Select animation for the reaction.
		**/
		public Sticker selectAnimation;

		/**
		 * Activate animation for the reaction.
		**/
		public Sticker activateAnimation;

		/**
		 * Effect animation for the reaction.
		**/
		public Sticker effectAnimation;

		/**
		 * Around animation for the reaction; may be null.
		**/
		public Sticker aroundAnimation;

		/**
		 * Center animation for the reaction; may be null.
		**/
		public Sticker centerAnimation;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1616063583;

		/**
		 * Contains information about a emoji reaction.
		**/
		public EmojiReaction() {}

		/**
		 * Contains information about a emoji reaction.
		 *
		 * @param emoji Text representation of the reaction.
		 * @param title Reaction title.
		 * @param isActive True, if the reaction can be added to new messages and enabled in chats.
		 * @param staticIcon Static icon for the reaction.
		 * @param appearAnimation Appear animation for the reaction.
		 * @param selectAnimation Select animation for the reaction.
		 * @param activateAnimation Activate animation for the reaction.
		 * @param effectAnimation Effect animation for the reaction.
		 * @param aroundAnimation Around animation for the reaction; may be null.
		 * @param centerAnimation Center animation for the reaction; may be null.
		**/
		public EmojiReaction(String emoji,
				String title,
				boolean isActive,
				Sticker staticIcon,
				Sticker appearAnimation,
				Sticker selectAnimation,
				Sticker activateAnimation,
				Sticker effectAnimation,
				Sticker aroundAnimation,
				Sticker centerAnimation) {
			this.emoji = emoji;
			this.title = title;
			this.isActive = isActive;
			this.staticIcon = staticIcon;
			this.appearAnimation = appearAnimation;
			this.selectAnimation = selectAnimation;
			this.activateAnimation = activateAnimation;
			this.effectAnimation = effectAnimation;
			this.aroundAnimation = aroundAnimation;
			this.centerAnimation = centerAnimation;
		}

		/**
		 * Contains information about a emoji reaction.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public EmojiReaction(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] emojiTmp = new byte[input.readInt()];
				input.readFully(emojiTmp);
				this.emoji = new String(emojiTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
			this.isActive = input.readBoolean();
			if (input.readBoolean()) {
				if (Sticker.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.staticIcon = new Sticker(input);
			}
			if (input.readBoolean()) {
				if (Sticker.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.appearAnimation = new Sticker(input);
			}
			if (input.readBoolean()) {
				if (Sticker.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.selectAnimation = new Sticker(input);
			}
			if (input.readBoolean()) {
				if (Sticker.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.activateAnimation = new Sticker(input);
			}
			if (input.readBoolean()) {
				if (Sticker.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.effectAnimation = new Sticker(input);
			}
			if (input.readBoolean()) {
				if (Sticker.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.aroundAnimation = new Sticker(input);
			}
			if (input.readBoolean()) {
				if (Sticker.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.centerAnimation = new Sticker(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return EmojiReaction.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(EmojiReaction.CONSTRUCTOR);
			if (this.emoji == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] emojiTmp = this.emoji.getBytes(StandardCharsets.UTF_8);
				output.writeInt(emojiTmp.length);
				output.write(emojiTmp);
			}
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
			output.writeBoolean(this.isActive);
			if (this.staticIcon == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.staticIcon.serialize(output);
			}
			if (this.appearAnimation == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.appearAnimation.serialize(output);
			}
			if (this.selectAnimation == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.selectAnimation.serialize(output);
			}
			if (this.activateAnimation == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.activateAnimation.serialize(output);
			}
			if (this.effectAnimation == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.effectAnimation.serialize(output);
			}
			if (this.aroundAnimation == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.aroundAnimation.serialize(output);
			}
			if (this.centerAnimation == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.centerAnimation.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			EmojiReaction emojiReaction = (EmojiReaction) o;
			if (this.emoji != emojiReaction.emoji) {
				return false;
			}
			if (this.title != emojiReaction.title) {
				return false;
			}
			if (this.isActive != emojiReaction.isActive) {
				return false;
			}
			if (!Objects.equals(this.staticIcon, emojiReaction.staticIcon)) {
				return false;
			}
			if (!Objects.equals(this.appearAnimation, emojiReaction.appearAnimation)) {
				return false;
			}
			if (!Objects.equals(this.selectAnimation, emojiReaction.selectAnimation)) {
				return false;
			}
			if (!Objects.equals(this.activateAnimation, emojiReaction.activateAnimation)) {
				return false;
			}
			if (!Objects.equals(this.effectAnimation, emojiReaction.effectAnimation)) {
				return false;
			}
			if (!Objects.equals(this.aroundAnimation, emojiReaction.aroundAnimation)) {
				return false;
			}
			if (!Objects.equals(this.centerAnimation, emojiReaction.centerAnimation)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isActive);
			result = result * 31 + (this.emoji == null ? 0 : this.emoji.hashCode());
			result = result * 31 + (this.title == null ? 0 : this.title.hashCode());
			result = result * 31 + (this.staticIcon == null ? 0 : this.staticIcon.hashCode());
			result = result * 31 + (this.appearAnimation == null ? 0 : this.appearAnimation.hashCode());
			result = result * 31 + (this.selectAnimation == null ? 0 : this.selectAnimation.hashCode());
			result = result * 31 + (this.activateAnimation == null ? 0 : this.activateAnimation.hashCode());
			result = result * 31 + (this.effectAnimation == null ? 0 : this.effectAnimation.hashCode());
			result = result * 31 + (this.aroundAnimation == null ? 0 : this.aroundAnimation.hashCode());
			result = result * 31 + (this.centerAnimation == null ? 0 : this.centerAnimation.hashCode());
			return result;
		}
	}

	/**
	 * Describes a custom emoji to be shown instead of the Telegram Premium
	 * badge.
	**/
	public static final class EmojiStatus extends Object {


		/**
		 * Identifier of the custom emoji in stickerFormatTgs format.
		**/
		public long customEmojiId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1092133478;

		/**
		 * Describes a custom emoji to be shown instead of the Telegram Premium badge.
		**/
		public EmojiStatus() {}

		/**
		 * Describes a custom emoji to be shown instead of the Telegram Premium badge.
		 *
		 * @param customEmojiId Identifier of the custom emoji in stickerFormatTgs format.
		**/
		public EmojiStatus(long customEmojiId) {
			this.customEmojiId = customEmojiId;
		}

		/**
		 * Describes a custom emoji to be shown instead of the Telegram Premium badge.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public EmojiStatus(DataInput input) throws IOException {
			this.customEmojiId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return EmojiStatus.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(EmojiStatus.CONSTRUCTOR);
			output.writeLong(this.customEmojiId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			EmojiStatus emojiStatus = (EmojiStatus) o;
			if (this.customEmojiId != emojiStatus.customEmojiId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.customEmojiId);
		}
	}

	/**
	 * Contains a list of emoji statuses.
	**/
	public static final class EmojiStatuses extends Object {


		/**
		 * The list of emoji statuses.
		**/
		public EmojiStatus[] emojiStatuses;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1186104146;

		/**
		 * Contains a list of emoji statuses.
		**/
		public EmojiStatuses() {}

		/**
		 * Contains a list of emoji statuses.
		 *
		 * @param emojiStatuses The list of emoji statuses.
		**/
		public EmojiStatuses(EmojiStatus[] emojiStatuses) {
			this.emojiStatuses = emojiStatuses;
		}

		/**
		 * Contains a list of emoji statuses.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public EmojiStatuses(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.emojiStatuses = new EmojiStatus[input.readInt()];
				for (int i = 0; i < this.emojiStatuses.length; i++) {
					if (EmojiStatus.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.emojiStatuses[i] = new EmojiStatus(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return EmojiStatuses.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(EmojiStatuses.CONSTRUCTOR);
			if (this.emojiStatuses == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.emojiStatuses.length);
				for (int i = 0; i < this.emojiStatuses.length; i++) {
					this.emojiStatuses[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			EmojiStatuses emojiStatuses = (EmojiStatuses) o;
			if (!Arrays.equals(this.emojiStatuses, emojiStatuses.emojiStatuses)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.emojiStatuses);
		}
	}

	/**
	 * Represents a list of emoji.
	**/
	public static final class Emojis extends Object {


		/**
		 * List of emojis.
		**/
		public String[] emojis;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 950339552;

		/**
		 * Represents a list of emoji.
		**/
		public Emojis() {}

		/**
		 * Represents a list of emoji.
		 *
		 * @param emojis List of emojis.
		**/
		public Emojis(String[] emojis) {
			this.emojis = emojis;
		}

		/**
		 * Represents a list of emoji.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public Emojis(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.emojis = new String[input.readInt()];
				for (int i = 0; i < this.emojis.length; i++) {
					byte[] emojisTmp = new byte[input.readInt()];
					input.readFully(emojisTmp);
					this.emojis[i] = new String(emojisTmp, StandardCharsets.UTF_8);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return Emojis.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(Emojis.CONSTRUCTOR);
			if (this.emojis == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.emojis.length);
				for (int i = 0; i < this.emojis.length; i++) {
					byte[] emojisTmp = this.emojis[i].getBytes(StandardCharsets.UTF_8);
					output.writeInt(emojisTmp.length);
					output.write(emojisTmp);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			Emojis emojis = (Emojis) o;
			if (!Arrays.equals(this.emojis, emojis.emojis)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.emojis);
		}
	}

	/**
	 * Contains encrypted Telegram Passport data credentials.
	**/
	public static final class EncryptedCredentials extends Object {


		/**
		 * The encrypted credentials.
		**/
		public byte[] data;

		/**
		 * The decrypted data hash.
		**/
		public byte[] hash;

		/**
		 * Secret for data decryption, encrypted with the service&#039;s public key.
		**/
		public byte[] secret;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1331106766;

		/**
		 * Contains encrypted Telegram Passport data credentials.
		**/
		public EncryptedCredentials() {}

		/**
		 * Contains encrypted Telegram Passport data credentials.
		 *
		 * @param data The encrypted credentials.
		 * @param hash The decrypted data hash.
		 * @param secret Secret for data decryption, encrypted with the service&#039;s public key.
		**/
		public EncryptedCredentials(byte[] data, byte[] hash, byte[] secret) {
			this.data = data;
			this.hash = hash;
			this.secret = secret;
		}

		/**
		 * Contains encrypted Telegram Passport data credentials.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public EncryptedCredentials(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.data = new byte[input.readInt()];
				input.readFully(this.data);
			}
			if (input.readBoolean()) {
				this.hash = new byte[input.readInt()];
				input.readFully(this.hash);
			}
			if (input.readBoolean()) {
				this.secret = new byte[input.readInt()];
				input.readFully(this.secret);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return EncryptedCredentials.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(EncryptedCredentials.CONSTRUCTOR);
			if (this.data == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.data.length);
				output.write(this.data);
			}
			if (this.hash == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.hash.length);
				output.write(this.hash);
			}
			if (this.secret == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.secret.length);
				output.write(this.secret);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			EncryptedCredentials encryptedCredentials = (EncryptedCredentials) o;
			if (this.data != encryptedCredentials.data) {
				return false;
			}
			if (this.hash != encryptedCredentials.hash) {
				return false;
			}
			if (this.secret != encryptedCredentials.secret) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Arrays.hashCode(this.data);
			result = result * 31 + (Arrays.hashCode(this.hash));
			result = result * 31 + (Arrays.hashCode(this.secret));
			return result;
		}
	}

	/**
	 * Contains information about an encrypted Telegram Passport element;
	 * for bots only.
	**/
	public static final class EncryptedPassportElement extends Object {


		/**
		 * Type of Telegram Passport element.
		**/
		public PassportElementType type;

		/**
		 * Encrypted JSON-encoded data about the user.
		**/
		public byte[] data;

		/**
		 * The front side of an identity document.
		**/
		public DatedFile frontSide;

		/**
		 * The reverse side of an identity document; may be null.
		**/
		public DatedFile reverseSide;

		/**
		 * Selfie with the document; may be null.
		**/
		public DatedFile selfie;

		/**
		 * List of files containing a certified English translation of the document.
		**/
		public DatedFile[] translation;

		/**
		 * List of attached files.
		**/
		public DatedFile[] files;

		/**
		 * Unencrypted data, phone number or email address.
		**/
		public String value;

		/**
		 * Hash of the entire element.
		**/
		public String hash;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2002386193;

		/**
		 * Contains information about an encrypted Telegram Passport element; for bots only.
		**/
		public EncryptedPassportElement() {}

		/**
		 * Contains information about an encrypted Telegram Passport element; for bots only.
		 *
		 * @param type Type of Telegram Passport element.
		 * @param data Encrypted JSON-encoded data about the user.
		 * @param frontSide The front side of an identity document.
		 * @param reverseSide The reverse side of an identity document; may be null.
		 * @param selfie Selfie with the document; may be null.
		 * @param translation List of files containing a certified English translation of the document.
		 * @param files List of attached files.
		 * @param value Unencrypted data, phone number or email address.
		 * @param hash Hash of the entire element.
		**/
		public EncryptedPassportElement(PassportElementType type,
				byte[] data,
				DatedFile frontSide,
				DatedFile reverseSide,
				DatedFile selfie,
				DatedFile[] translation,
				DatedFile[] files,
				String value,
				String hash) {
			this.type = type;
			this.data = data;
			this.frontSide = frontSide;
			this.reverseSide = reverseSide;
			this.selfie = selfie;
			this.translation = translation;
			this.files = files;
			this.value = value;
			this.hash = hash;
		}

		/**
		 * Contains information about an encrypted Telegram Passport element; for bots only.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public EncryptedPassportElement(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case PassportElementTypePersonalDetails.CONSTRUCTOR: this.type = new PassportElementTypePersonalDetails(input); break;
					case PassportElementTypePassport.CONSTRUCTOR: this.type = new PassportElementTypePassport(input); break;
					case PassportElementTypeDriverLicense.CONSTRUCTOR: this.type = new PassportElementTypeDriverLicense(input); break;
					case PassportElementTypeIdentityCard.CONSTRUCTOR: this.type = new PassportElementTypeIdentityCard(input); break;
					case PassportElementTypeInternalPassport.CONSTRUCTOR: this.type = new PassportElementTypeInternalPassport(input); break;
					case PassportElementTypeAddress.CONSTRUCTOR: this.type = new PassportElementTypeAddress(input); break;
					case PassportElementTypeUtilityBill.CONSTRUCTOR: this.type = new PassportElementTypeUtilityBill(input); break;
					case PassportElementTypeBankStatement.CONSTRUCTOR: this.type = new PassportElementTypeBankStatement(input); break;
					case PassportElementTypeRentalAgreement.CONSTRUCTOR: this.type = new PassportElementTypeRentalAgreement(input); break;
					case PassportElementTypePassportRegistration.CONSTRUCTOR: this.type = new PassportElementTypePassportRegistration(input); break;
					case PassportElementTypeTemporaryRegistration.CONSTRUCTOR: this.type = new PassportElementTypeTemporaryRegistration(input); break;
					case PassportElementTypePhoneNumber.CONSTRUCTOR: this.type = new PassportElementTypePhoneNumber(input); break;
					case PassportElementTypeEmailAddress.CONSTRUCTOR: this.type = new PassportElementTypeEmailAddress(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				this.data = new byte[input.readInt()];
				input.readFully(this.data);
			}
			if (input.readBoolean()) {
				if (DatedFile.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.frontSide = new DatedFile(input);
			}
			if (input.readBoolean()) {
				if (DatedFile.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.reverseSide = new DatedFile(input);
			}
			if (input.readBoolean()) {
				if (DatedFile.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.selfie = new DatedFile(input);
			}
			if (input.readBoolean()) {
				this.translation = new DatedFile[input.readInt()];
				for (int i = 0; i < this.translation.length; i++) {
					if (DatedFile.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.translation[i] = new DatedFile(input);
				}
			}
			if (input.readBoolean()) {
				this.files = new DatedFile[input.readInt()];
				for (int i = 0; i < this.files.length; i++) {
					if (DatedFile.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.files[i] = new DatedFile(input);
				}
			}
			if (input.readBoolean()) {
				byte[] valueTmp = new byte[input.readInt()];
				input.readFully(valueTmp);
				this.value = new String(valueTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] hashTmp = new byte[input.readInt()];
				input.readFully(hashTmp);
				this.hash = new String(hashTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return EncryptedPassportElement.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(EncryptedPassportElement.CONSTRUCTOR);
			if (this.type == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.type.serialize(output);
			}
			if (this.data == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.data.length);
				output.write(this.data);
			}
			if (this.frontSide == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.frontSide.serialize(output);
			}
			if (this.reverseSide == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.reverseSide.serialize(output);
			}
			if (this.selfie == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.selfie.serialize(output);
			}
			if (this.translation == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.translation.length);
				for (int i = 0; i < this.translation.length; i++) {
					this.translation[i].serialize(output);
				}
			}
			if (this.files == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.files.length);
				for (int i = 0; i < this.files.length; i++) {
					this.files[i].serialize(output);
				}
			}
			if (this.value == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] valueTmp = this.value.getBytes(StandardCharsets.UTF_8);
				output.writeInt(valueTmp.length);
				output.write(valueTmp);
			}
			if (this.hash == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] hashTmp = this.hash.getBytes(StandardCharsets.UTF_8);
				output.writeInt(hashTmp.length);
				output.write(hashTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			EncryptedPassportElement encryptedPassportElement = (EncryptedPassportElement) o;
			if (!Objects.equals(this.type, encryptedPassportElement.type)) {
				return false;
			}
			if (this.data != encryptedPassportElement.data) {
				return false;
			}
			if (!Objects.equals(this.frontSide, encryptedPassportElement.frontSide)) {
				return false;
			}
			if (!Objects.equals(this.reverseSide, encryptedPassportElement.reverseSide)) {
				return false;
			}
			if (!Objects.equals(this.selfie, encryptedPassportElement.selfie)) {
				return false;
			}
			if (!Arrays.equals(this.translation, encryptedPassportElement.translation)) {
				return false;
			}
			if (!Arrays.equals(this.files, encryptedPassportElement.files)) {
				return false;
			}
			if (this.value != encryptedPassportElement.value) {
				return false;
			}
			if (this.hash != encryptedPassportElement.hash) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.type == null ? 0 : this.type.hashCode();
			result = result * 31 + (Arrays.hashCode(this.data));
			result = result * 31 + (this.frontSide == null ? 0 : this.frontSide.hashCode());
			result = result * 31 + (this.reverseSide == null ? 0 : this.reverseSide.hashCode());
			result = result * 31 + (this.selfie == null ? 0 : this.selfie.hashCode());
			result = result * 31 + (Arrays.hashCode(this.translation));
			result = result * 31 + (Arrays.hashCode(this.files));
			result = result * 31 + (this.value == null ? 0 : this.value.hashCode());
			result = result * 31 + (this.hash == null ? 0 : this.hash.hashCode());
			return result;
		}
	}

	/**
	 * An object of this type can be returned on every function call, in
	 * case of an error.
	**/
	public static final class Error extends Object {


		/**
		 * Error code; subject to future changes. If the error code is 406, the error message must not be processed in any way and must not be displayed to the user.
		**/
		public int code;

		/**
		 * Error message; subject to future changes.
		**/
		public String message;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1679978726;

		/**
		 * An object of this type can be returned on every function call, in case of an error.
		**/
		public Error() {}

		/**
		 * An object of this type can be returned on every function call, in case of an error.
		 *
		 * @param code Error code; subject to future changes. If the error code is 406, the error message must not be processed in any way and must not be displayed to the user.
		 * @param message Error message; subject to future changes.
		**/
		public Error(int code, String message) {
			this.code = code;
			this.message = message;
		}

		/**
		 * An object of this type can be returned on every function call, in case of an error.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public Error(DataInput input) throws IOException {
			this.code = input.readInt();
			if (input.readBoolean()) {
				byte[] messageTmp = new byte[input.readInt()];
				input.readFully(messageTmp);
				this.message = new String(messageTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return Error.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(Error.CONSTRUCTOR);
			output.writeInt(this.code);
			if (this.message == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] messageTmp = this.message.getBytes(StandardCharsets.UTF_8);
				output.writeInt(messageTmp.length);
				output.write(messageTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			Error error = (Error) o;
			if (this.code != error.code) {
				return false;
			}
			if (this.message != error.message) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.code);
			result = result * 31 + (this.message == null ? 0 : this.message.hashCode());
			return result;
		}
	}

	/**
	 * Represents a file.
	**/
	public static final class File extends Object {


		/**
		 * Unique file identifier.
		**/
		public int id;

		/**
		 * File size, in bytes; 0 if unknown.
		**/
		public long size;

		/**
		 * Approximate file size in bytes in case the exact file size is unknown. Can be used to show download/upload progress.
		**/
		public long expectedSize;

		/**
		 * Information about the local copy of the file.
		**/
		public LocalFile local;

		/**
		 * Information about the remote copy of the file.
		**/
		public RemoteFile remote;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1263291956;

		/**
		 * Represents a file.
		**/
		public File() {}

		/**
		 * Represents a file.
		 *
		 * @param id Unique file identifier.
		 * @param size File size, in bytes; 0 if unknown.
		 * @param expectedSize Approximate file size in bytes in case the exact file size is unknown. Can be used to show download/upload progress.
		 * @param local Information about the local copy of the file.
		 * @param remote Information about the remote copy of the file.
		**/
		public File(int id,
				long size,
				long expectedSize,
				LocalFile local,
				RemoteFile remote) {
			this.id = id;
			this.size = size;
			this.expectedSize = expectedSize;
			this.local = local;
			this.remote = remote;
		}

		/**
		 * Represents a file.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public File(DataInput input) throws IOException {
			this.id = input.readInt();
			this.size = input.readLong();
			this.expectedSize = input.readLong();
			if (input.readBoolean()) {
				if (LocalFile.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.local = new LocalFile(input);
			}
			if (input.readBoolean()) {
				if (RemoteFile.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.remote = new RemoteFile(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return File.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(File.CONSTRUCTOR);
			output.writeInt(this.id);
			output.writeLong(this.size);
			output.writeLong(this.expectedSize);
			if (this.local == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.local.serialize(output);
			}
			if (this.remote == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.remote.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			File file = (File) o;
			if (this.id != file.id) {
				return false;
			}
			if (this.size != file.size) {
				return false;
			}
			if (this.expectedSize != file.expectedSize) {
				return false;
			}
			if (!Objects.equals(this.local, file.local)) {
				return false;
			}
			if (!Objects.equals(this.remote, file.remote)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.id);
			result = result * 31 + (this.local == null ? 0 : this.local.hashCode());
			result = result * 31 + (this.remote == null ? 0 : this.remote.hashCode());
			return result;
		}
	}

	/**
	 * Describes a file added to file download list.
	**/
	public static final class FileDownload extends Object {


		/**
		 * File identifier.
		**/
		public int fileId;

		/**
		 * The message with the file.
		**/
		public Message message;

		/**
		 * Point in time (Unix timestamp) when the file was added to the download list.
		**/
		public int addDate;

		/**
		 * Point in time (Unix timestamp) when the file downloading was completed; 0 if the file downloading isn&#039;t completed.
		**/
		public int completeDate;

		/**
		 * True, if downloading of the file is paused.
		**/
		public boolean isPaused;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2092100780;

		/**
		 * Describes a file added to file download list.
		**/
		public FileDownload() {}

		/**
		 * Describes a file added to file download list.
		 *
		 * @param fileId File identifier.
		 * @param message The message with the file.
		 * @param addDate Point in time (Unix timestamp) when the file was added to the download list.
		 * @param completeDate Point in time (Unix timestamp) when the file downloading was completed; 0 if the file downloading isn&#039;t completed.
		 * @param isPaused True, if downloading of the file is paused.
		**/
		public FileDownload(int fileId,
				Message message,
				int addDate,
				int completeDate,
				boolean isPaused) {
			this.fileId = fileId;
			this.message = message;
			this.addDate = addDate;
			this.completeDate = completeDate;
			this.isPaused = isPaused;
		}

		/**
		 * Describes a file added to file download list.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public FileDownload(DataInput input) throws IOException {
			this.fileId = input.readInt();
			if (input.readBoolean()) {
				if (Message.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.message = new Message(input);
			}
			this.addDate = input.readInt();
			this.completeDate = input.readInt();
			this.isPaused = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return FileDownload.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(FileDownload.CONSTRUCTOR);
			output.writeInt(this.fileId);
			if (this.message == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.message.serialize(output);
			}
			output.writeInt(this.addDate);
			output.writeInt(this.completeDate);
			output.writeBoolean(this.isPaused);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			FileDownload fileDownload = (FileDownload) o;
			if (this.fileId != fileDownload.fileId) {
				return false;
			}
			if (!Objects.equals(this.message, fileDownload.message)) {
				return false;
			}
			if (this.addDate != fileDownload.addDate) {
				return false;
			}
			if (this.completeDate != fileDownload.completeDate) {
				return false;
			}
			if (this.isPaused != fileDownload.isPaused) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.fileId);
			result = result * 31 + (this.message == null ? 0 : this.message.hashCode());
			return result;
		}
	}

	/**
	 * Contains size of downloaded prefix of a file.
	**/
	public static final class FileDownloadedPrefixSize extends Object {


		/**
		 * The prefix size, in bytes.
		**/
		public long size;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2015205381;

		/**
		 * Contains size of downloaded prefix of a file.
		**/
		public FileDownloadedPrefixSize() {}

		/**
		 * Contains size of downloaded prefix of a file.
		 *
		 * @param size The prefix size, in bytes.
		**/
		public FileDownloadedPrefixSize(long size) {
			this.size = size;
		}

		/**
		 * Contains size of downloaded prefix of a file.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public FileDownloadedPrefixSize(DataInput input) throws IOException {
			this.size = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return FileDownloadedPrefixSize.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(FileDownloadedPrefixSize.CONSTRUCTOR);
			output.writeLong(this.size);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			FileDownloadedPrefixSize fileDownloadedPrefixSize = (FileDownloadedPrefixSize) o;
			if (this.size != fileDownloadedPrefixSize.size) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.size);
		}
	}

	/**
	 * Contains a part of a file.
	**/
	public static final class FilePart extends Object {


		/**
		 * File bytes.
		**/
		public byte[] data;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 911821878;

		/**
		 * Contains a part of a file.
		**/
		public FilePart() {}

		/**
		 * Contains a part of a file.
		 *
		 * @param data File bytes.
		**/
		public FilePart(byte[] data) {
			this.data = data;
		}

		/**
		 * Contains a part of a file.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public FilePart(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.data = new byte[input.readInt()];
				input.readFully(this.data);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return FilePart.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(FilePart.CONSTRUCTOR);
			if (this.data == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.data.length);
				output.write(this.data);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			FilePart filePart = (FilePart) o;
			if (this.data != filePart.data) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.data);
		}
	}

	/**
	 * The data is not a file.
	**/
	public static final class FileTypeNone extends FileType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2003009189;

		/**
		 * The data is not a file.
		**/
		public FileTypeNone() {}

		/**
		 * The data is not a file.
		 *
		**/

		/**
		 * The data is not a file.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public FileTypeNone(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return FileTypeNone.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(FileTypeNone.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return FileTypeNone.CONSTRUCTOR;
		}
	}

	/**
	 * The file is an animation.
	**/
	public static final class FileTypeAnimation extends FileType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -290816582;

		/**
		 * The file is an animation.
		**/
		public FileTypeAnimation() {}

		/**
		 * The file is an animation.
		 *
		**/

		/**
		 * The file is an animation.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public FileTypeAnimation(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return FileTypeAnimation.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(FileTypeAnimation.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return FileTypeAnimation.CONSTRUCTOR;
		}
	}

	/**
	 * The file is an audio file.
	**/
	public static final class FileTypeAudio extends FileType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -709112160;

		/**
		 * The file is an audio file.
		**/
		public FileTypeAudio() {}

		/**
		 * The file is an audio file.
		 *
		**/

		/**
		 * The file is an audio file.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public FileTypeAudio(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return FileTypeAudio.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(FileTypeAudio.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return FileTypeAudio.CONSTRUCTOR;
		}
	}

	/**
	 * The file is a document.
	**/
	public static final class FileTypeDocument extends FileType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -564722929;

		/**
		 * The file is a document.
		**/
		public FileTypeDocument() {}

		/**
		 * The file is a document.
		 *
		**/

		/**
		 * The file is a document.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public FileTypeDocument(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return FileTypeDocument.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(FileTypeDocument.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return FileTypeDocument.CONSTRUCTOR;
		}
	}

	/**
	 * The file is a notification sound.
	**/
	public static final class FileTypeNotificationSound extends FileType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1020289271;

		/**
		 * The file is a notification sound.
		**/
		public FileTypeNotificationSound() {}

		/**
		 * The file is a notification sound.
		 *
		**/

		/**
		 * The file is a notification sound.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public FileTypeNotificationSound(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return FileTypeNotificationSound.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(FileTypeNotificationSound.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return FileTypeNotificationSound.CONSTRUCTOR;
		}
	}

	/**
	 * The file is a photo.
	**/
	public static final class FileTypePhoto extends FileType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1718914651;

		/**
		 * The file is a photo.
		**/
		public FileTypePhoto() {}

		/**
		 * The file is a photo.
		 *
		**/

		/**
		 * The file is a photo.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public FileTypePhoto(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return FileTypePhoto.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(FileTypePhoto.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return FileTypePhoto.CONSTRUCTOR;
		}
	}

	/**
	 * The file is a profile photo.
	**/
	public static final class FileTypeProfilePhoto extends FileType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1795089315;

		/**
		 * The file is a profile photo.
		**/
		public FileTypeProfilePhoto() {}

		/**
		 * The file is a profile photo.
		 *
		**/

		/**
		 * The file is a profile photo.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public FileTypeProfilePhoto(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return FileTypeProfilePhoto.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(FileTypeProfilePhoto.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return FileTypeProfilePhoto.CONSTRUCTOR;
		}
	}

	/**
	 * The file was sent to a secret chat (the file type is not known to the
	 * server).
	**/
	public static final class FileTypeSecret extends FileType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1871899401;

		/**
		 * The file was sent to a secret chat (the file type is not known to the server).
		**/
		public FileTypeSecret() {}

		/**
		 * The file was sent to a secret chat (the file type is not known to the server).
		 *
		**/

		/**
		 * The file was sent to a secret chat (the file type is not known to the server).
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public FileTypeSecret(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return FileTypeSecret.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(FileTypeSecret.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return FileTypeSecret.CONSTRUCTOR;
		}
	}

	/**
	 * The file is a thumbnail of a file from a secret chat.
	**/
	public static final class FileTypeSecretThumbnail extends FileType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1401326026;

		/**
		 * The file is a thumbnail of a file from a secret chat.
		**/
		public FileTypeSecretThumbnail() {}

		/**
		 * The file is a thumbnail of a file from a secret chat.
		 *
		**/

		/**
		 * The file is a thumbnail of a file from a secret chat.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public FileTypeSecretThumbnail(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return FileTypeSecretThumbnail.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(FileTypeSecretThumbnail.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return FileTypeSecretThumbnail.CONSTRUCTOR;
		}
	}

	/**
	 * The file is a file from Secure storage used for storing Telegram
	 * Passport files.
	**/
	public static final class FileTypeSecure extends FileType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1419133146;

		/**
		 * The file is a file from Secure storage used for storing Telegram Passport files.
		**/
		public FileTypeSecure() {}

		/**
		 * The file is a file from Secure storage used for storing Telegram Passport files.
		 *
		**/

		/**
		 * The file is a file from Secure storage used for storing Telegram Passport files.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public FileTypeSecure(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return FileTypeSecure.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(FileTypeSecure.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return FileTypeSecure.CONSTRUCTOR;
		}
	}

	/**
	 * The file is a sticker.
	**/
	public static final class FileTypeSticker extends FileType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 475233385;

		/**
		 * The file is a sticker.
		**/
		public FileTypeSticker() {}

		/**
		 * The file is a sticker.
		 *
		**/

		/**
		 * The file is a sticker.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public FileTypeSticker(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return FileTypeSticker.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(FileTypeSticker.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return FileTypeSticker.CONSTRUCTOR;
		}
	}

	/**
	 * The file is a thumbnail of another file.
	**/
	public static final class FileTypeThumbnail extends FileType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -12443298;

		/**
		 * The file is a thumbnail of another file.
		**/
		public FileTypeThumbnail() {}

		/**
		 * The file is a thumbnail of another file.
		 *
		**/

		/**
		 * The file is a thumbnail of another file.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public FileTypeThumbnail(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return FileTypeThumbnail.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(FileTypeThumbnail.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return FileTypeThumbnail.CONSTRUCTOR;
		}
	}

	/**
	 * The file type is not yet known.
	**/
	public static final class FileTypeUnknown extends FileType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2011566768;

		/**
		 * The file type is not yet known.
		**/
		public FileTypeUnknown() {}

		/**
		 * The file type is not yet known.
		 *
		**/

		/**
		 * The file type is not yet known.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public FileTypeUnknown(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return FileTypeUnknown.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(FileTypeUnknown.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return FileTypeUnknown.CONSTRUCTOR;
		}
	}

	/**
	 * The file is a video.
	**/
	public static final class FileTypeVideo extends FileType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1430816539;

		/**
		 * The file is a video.
		**/
		public FileTypeVideo() {}

		/**
		 * The file is a video.
		 *
		**/

		/**
		 * The file is a video.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public FileTypeVideo(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return FileTypeVideo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(FileTypeVideo.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return FileTypeVideo.CONSTRUCTOR;
		}
	}

	/**
	 * The file is a video note.
	**/
	public static final class FileTypeVideoNote extends FileType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -518412385;

		/**
		 * The file is a video note.
		**/
		public FileTypeVideoNote() {}

		/**
		 * The file is a video note.
		 *
		**/

		/**
		 * The file is a video note.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public FileTypeVideoNote(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return FileTypeVideoNote.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(FileTypeVideoNote.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return FileTypeVideoNote.CONSTRUCTOR;
		}
	}

	/**
	 * The file is a voice note.
	**/
	public static final class FileTypeVoiceNote extends FileType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -588681661;

		/**
		 * The file is a voice note.
		**/
		public FileTypeVoiceNote() {}

		/**
		 * The file is a voice note.
		 *
		**/

		/**
		 * The file is a voice note.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public FileTypeVoiceNote(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return FileTypeVoiceNote.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(FileTypeVoiceNote.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return FileTypeVoiceNote.CONSTRUCTOR;
		}
	}

	/**
	 * The file is a wallpaper or a background pattern.
	**/
	public static final class FileTypeWallpaper extends FileType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1854930076;

		/**
		 * The file is a wallpaper or a background pattern.
		**/
		public FileTypeWallpaper() {}

		/**
		 * The file is a wallpaper or a background pattern.
		 *
		**/

		/**
		 * The file is a wallpaper or a background pattern.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public FileTypeWallpaper(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return FileTypeWallpaper.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(FileTypeWallpaper.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return FileTypeWallpaper.CONSTRUCTOR;
		}
	}

	/**
	 * Settings for Firebase Authentication in the official Android
	 * application.
	**/
	public static final class FirebaseAuthenticationSettingsAndroid extends FirebaseAuthenticationSettings {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1771112932;

		/**
		 * Settings for Firebase Authentication in the official Android application.
		**/
		public FirebaseAuthenticationSettingsAndroid() {}

		/**
		 * Settings for Firebase Authentication in the official Android application.
		 *
		**/

		/**
		 * Settings for Firebase Authentication in the official Android application.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public FirebaseAuthenticationSettingsAndroid(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return FirebaseAuthenticationSettingsAndroid.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(FirebaseAuthenticationSettingsAndroid.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return FirebaseAuthenticationSettingsAndroid.CONSTRUCTOR;
		}
	}

	/**
	 * Settings for Firebase Authentication in the official iOS application.
	**/
	public static final class FirebaseAuthenticationSettingsIos extends FirebaseAuthenticationSettings {


		/**
		 * Device token from Apple Push Notification service.
		**/
		public String deviceToken;

		/**
		 * True, if App Sandbox is enabled.
		**/
		public boolean isAppSandbox;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 222930116;

		/**
		 * Settings for Firebase Authentication in the official iOS application.
		**/
		public FirebaseAuthenticationSettingsIos() {}

		/**
		 * Settings for Firebase Authentication in the official iOS application.
		 *
		 * @param deviceToken Device token from Apple Push Notification service.
		 * @param isAppSandbox True, if App Sandbox is enabled.
		**/
		public FirebaseAuthenticationSettingsIos(String deviceToken, boolean isAppSandbox) {
			this.deviceToken = deviceToken;
			this.isAppSandbox = isAppSandbox;
		}

		/**
		 * Settings for Firebase Authentication in the official iOS application.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public FirebaseAuthenticationSettingsIos(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] deviceTokenTmp = new byte[input.readInt()];
				input.readFully(deviceTokenTmp);
				this.deviceToken = new String(deviceTokenTmp, StandardCharsets.UTF_8);
			}
			this.isAppSandbox = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return FirebaseAuthenticationSettingsIos.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(FirebaseAuthenticationSettingsIos.CONSTRUCTOR);
			if (this.deviceToken == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] deviceTokenTmp = this.deviceToken.getBytes(StandardCharsets.UTF_8);
				output.writeInt(deviceTokenTmp.length);
				output.write(deviceTokenTmp);
			}
			output.writeBoolean(this.isAppSandbox);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			FirebaseAuthenticationSettingsIos firebaseAuthenticationSettingsIos = (FirebaseAuthenticationSettingsIos) o;
			if (this.deviceToken != firebaseAuthenticationSettingsIos.deviceToken) {
				return false;
			}
			if (this.isAppSandbox != firebaseAuthenticationSettingsIos.isAppSandbox) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isAppSandbox);
			result = result * 31 + (this.deviceToken == null ? 0 : this.deviceToken.hashCode());
			return result;
		}
	}

	/**
	 * A text with some entities.
	**/
	public static final class FormattedText extends Object {


		/**
		 * The text.
		**/
		public String text;

		/**
		 * Entities contained in the text. Entities can be nested, but must not mutually intersect with each other. Pre, Code and PreCode entities can&#039;t contain other entities. Bold, Italic, Underline, Strikethrough, and Spoiler entities can contain and can be part of any other entities. All other entities can&#039;t contain each other.
		**/
		public TextEntity[] entities;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -252624564;

		/**
		 * A text with some entities.
		**/
		public FormattedText() {}

		/**
		 * A text with some entities.
		 *
		 * @param text The text.
		 * @param entities Entities contained in the text. Entities can be nested, but must not mutually intersect with each other. Pre, Code and PreCode entities can&#039;t contain other entities. Bold, Italic, Underline, Strikethrough, and Spoiler entities can contain and can be part of any other entities. All other entities can&#039;t contain each other.
		**/
		public FormattedText(String text, TextEntity[] entities) {
			this.text = text;
			this.entities = entities;
		}

		/**
		 * A text with some entities.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public FormattedText(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] textTmp = new byte[input.readInt()];
				input.readFully(textTmp);
				this.text = new String(textTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				this.entities = new TextEntity[input.readInt()];
				for (int i = 0; i < this.entities.length; i++) {
					if (TextEntity.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.entities[i] = new TextEntity(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return FormattedText.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(FormattedText.CONSTRUCTOR);
			if (this.text == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] textTmp = this.text.getBytes(StandardCharsets.UTF_8);
				output.writeInt(textTmp.length);
				output.write(textTmp);
			}
			if (this.entities == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.entities.length);
				for (int i = 0; i < this.entities.length; i++) {
					this.entities[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			FormattedText formattedText = (FormattedText) o;
			if (this.text != formattedText.text) {
				return false;
			}
			if (!Arrays.equals(this.entities, formattedText.entities)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.text == null ? 0 : this.text.hashCode();
			result = result * 31 + (Arrays.hashCode(this.entities));
			return result;
		}
	}

	/**
	 * Describes a forum topic.
	**/
	public static final class ForumTopic extends Object {


		/**
		 * Basic information about the topic.
		**/
		public ForumTopicInfo info;

		/**
		 * Last message in the topic; may be null if unknown.
		**/
		public Message lastMessage;

		/**
		 * True, if the topic is pinned in the topic list.
		**/
		public boolean isPinned;

		/**
		 * Number of unread messages in the topic.
		**/
		public int unreadCount;

		/**
		 * Identifier of the last read incoming message.
		**/
		public long lastReadInboxMessageId;

		/**
		 * Identifier of the last read outgoing message.
		**/
		public long lastReadOutboxMessageId;

		/**
		 * Number of unread messages with a mention/reply in the topic.
		**/
		public int unreadMentionCount;

		/**
		 * Number of messages with unread reactions in the topic.
		**/
		public int unreadReactionCount;

		/**
		 * Notification settings for the topic.
		**/
		public ChatNotificationSettings notificationSettings;

		/**
		 * A draft of a message in the topic; may be null.
		**/
		public DraftMessage draftMessage;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 303279334;

		/**
		 * Describes a forum topic.
		**/
		public ForumTopic() {}

		/**
		 * Describes a forum topic.
		 *
		 * @param info Basic information about the topic.
		 * @param lastMessage Last message in the topic; may be null if unknown.
		 * @param isPinned True, if the topic is pinned in the topic list.
		 * @param unreadCount Number of unread messages in the topic.
		 * @param lastReadInboxMessageId Identifier of the last read incoming message.
		 * @param lastReadOutboxMessageId Identifier of the last read outgoing message.
		 * @param unreadMentionCount Number of unread messages with a mention/reply in the topic.
		 * @param unreadReactionCount Number of messages with unread reactions in the topic.
		 * @param notificationSettings Notification settings for the topic.
		 * @param draftMessage A draft of a message in the topic; may be null.
		**/
		public ForumTopic(ForumTopicInfo info,
				Message lastMessage,
				boolean isPinned,
				int unreadCount,
				long lastReadInboxMessageId,
				long lastReadOutboxMessageId,
				int unreadMentionCount,
				int unreadReactionCount,
				ChatNotificationSettings notificationSettings,
				DraftMessage draftMessage) {
			this.info = info;
			this.lastMessage = lastMessage;
			this.isPinned = isPinned;
			this.unreadCount = unreadCount;
			this.lastReadInboxMessageId = lastReadInboxMessageId;
			this.lastReadOutboxMessageId = lastReadOutboxMessageId;
			this.unreadMentionCount = unreadMentionCount;
			this.unreadReactionCount = unreadReactionCount;
			this.notificationSettings = notificationSettings;
			this.draftMessage = draftMessage;
		}

		/**
		 * Describes a forum topic.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ForumTopic(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (ForumTopicInfo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.info = new ForumTopicInfo(input);
			}
			if (input.readBoolean()) {
				if (Message.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.lastMessage = new Message(input);
			}
			this.isPinned = input.readBoolean();
			this.unreadCount = input.readInt();
			this.lastReadInboxMessageId = input.readLong();
			this.lastReadOutboxMessageId = input.readLong();
			this.unreadMentionCount = input.readInt();
			this.unreadReactionCount = input.readInt();
			if (input.readBoolean()) {
				if (ChatNotificationSettings.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.notificationSettings = new ChatNotificationSettings(input);
			}
			if (input.readBoolean()) {
				if (DraftMessage.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.draftMessage = new DraftMessage(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ForumTopic.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ForumTopic.CONSTRUCTOR);
			if (this.info == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.info.serialize(output);
			}
			if (this.lastMessage == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.lastMessage.serialize(output);
			}
			output.writeBoolean(this.isPinned);
			output.writeInt(this.unreadCount);
			output.writeLong(this.lastReadInboxMessageId);
			output.writeLong(this.lastReadOutboxMessageId);
			output.writeInt(this.unreadMentionCount);
			output.writeInt(this.unreadReactionCount);
			if (this.notificationSettings == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.notificationSettings.serialize(output);
			}
			if (this.draftMessage == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.draftMessage.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ForumTopic forumTopic = (ForumTopic) o;
			if (!Objects.equals(this.info, forumTopic.info)) {
				return false;
			}
			if (!Objects.equals(this.lastMessage, forumTopic.lastMessage)) {
				return false;
			}
			if (this.isPinned != forumTopic.isPinned) {
				return false;
			}
			if (this.unreadCount != forumTopic.unreadCount) {
				return false;
			}
			if (this.lastReadInboxMessageId != forumTopic.lastReadInboxMessageId) {
				return false;
			}
			if (this.lastReadOutboxMessageId != forumTopic.lastReadOutboxMessageId) {
				return false;
			}
			if (this.unreadMentionCount != forumTopic.unreadMentionCount) {
				return false;
			}
			if (this.unreadReactionCount != forumTopic.unreadReactionCount) {
				return false;
			}
			if (!Objects.equals(this.notificationSettings, forumTopic.notificationSettings)) {
				return false;
			}
			if (!Objects.equals(this.draftMessage, forumTopic.draftMessage)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isPinned);
			result = result * 31 + (this.info == null ? 0 : this.info.hashCode());
			result = result * 31 + (this.lastMessage == null ? 0 : this.lastMessage.hashCode());
			result = result * 31 + (this.notificationSettings == null ? 0 : this.notificationSettings.hashCode());
			result = result * 31 + (this.draftMessage == null ? 0 : this.draftMessage.hashCode());
			return result;
		}
	}

	/**
	 * Describes a forum topic icon.
	**/
	public static final class ForumTopicIcon extends Object {


		/**
		 * Color of the topic icon in RGB format.
		**/
		public int color;

		/**
		 * Unique identifier of the custom emoji shown on the topic icon; 0 if none.
		**/
		public long customEmojiId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -818765421;

		/**
		 * Describes a forum topic icon.
		**/
		public ForumTopicIcon() {}

		/**
		 * Describes a forum topic icon.
		 *
		 * @param color Color of the topic icon in RGB format.
		 * @param customEmojiId Unique identifier of the custom emoji shown on the topic icon; 0 if none.
		**/
		public ForumTopicIcon(int color, long customEmojiId) {
			this.color = color;
			this.customEmojiId = customEmojiId;
		}

		/**
		 * Describes a forum topic icon.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ForumTopicIcon(DataInput input) throws IOException {
			this.color = input.readInt();
			this.customEmojiId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ForumTopicIcon.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ForumTopicIcon.CONSTRUCTOR);
			output.writeInt(this.color);
			output.writeLong(this.customEmojiId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ForumTopicIcon forumTopicIcon = (ForumTopicIcon) o;
			if (this.color != forumTopicIcon.color) {
				return false;
			}
			if (this.customEmojiId != forumTopicIcon.customEmojiId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.color);
			return result;
		}
	}

	/**
	 * Contains basic information about a forum topic.
	**/
	public static final class ForumTopicInfo extends Object {


		/**
		 * Message thread identifier of the topic.
		**/
		public long messageThreadId;

		/**
		 * Name of the topic.
		**/
		public String name;

		/**
		 * Icon of the topic.
		**/
		public ForumTopicIcon icon;

		/**
		 * Date the topic was created.
		**/
		public int creationDate;

		/**
		 * Identifier of the creator of the topic.
		**/
		public MessageSender creatorId;

		/**
		 * True, if the topic is the General topic list.
		**/
		public boolean isGeneral;

		/**
		 * True, if the topic was created by the current user.
		**/
		public boolean isOutgoing;

		/**
		 * True, if the topic is closed.
		**/
		public boolean isClosed;

		/**
		 * True, if the topic is hidden above the topic list and closed; for General topic only.
		**/
		public boolean isHidden;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1879842914;

		/**
		 * Contains basic information about a forum topic.
		**/
		public ForumTopicInfo() {}

		/**
		 * Contains basic information about a forum topic.
		 *
		 * @param messageThreadId Message thread identifier of the topic.
		 * @param name Name of the topic.
		 * @param icon Icon of the topic.
		 * @param creationDate Date the topic was created.
		 * @param creatorId Identifier of the creator of the topic.
		 * @param isGeneral True, if the topic is the General topic list.
		 * @param isOutgoing True, if the topic was created by the current user.
		 * @param isClosed True, if the topic is closed.
		 * @param isHidden True, if the topic is hidden above the topic list and closed; for General topic only.
		**/
		public ForumTopicInfo(long messageThreadId,
				String name,
				ForumTopicIcon icon,
				int creationDate,
				MessageSender creatorId,
				boolean isGeneral,
				boolean isOutgoing,
				boolean isClosed,
				boolean isHidden) {
			this.messageThreadId = messageThreadId;
			this.name = name;
			this.icon = icon;
			this.creationDate = creationDate;
			this.creatorId = creatorId;
			this.isGeneral = isGeneral;
			this.isOutgoing = isOutgoing;
			this.isClosed = isClosed;
			this.isHidden = isHidden;
		}

		/**
		 * Contains basic information about a forum topic.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ForumTopicInfo(DataInput input) throws IOException {
			this.messageThreadId = input.readLong();
			if (input.readBoolean()) {
				byte[] nameTmp = new byte[input.readInt()];
				input.readFully(nameTmp);
				this.name = new String(nameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (ForumTopicIcon.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.icon = new ForumTopicIcon(input);
			}
			this.creationDate = input.readInt();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case MessageSenderUser.CONSTRUCTOR: this.creatorId = new MessageSenderUser(input); break;
					case MessageSenderChat.CONSTRUCTOR: this.creatorId = new MessageSenderChat(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.isGeneral = input.readBoolean();
			this.isOutgoing = input.readBoolean();
			this.isClosed = input.readBoolean();
			this.isHidden = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ForumTopicInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ForumTopicInfo.CONSTRUCTOR);
			output.writeLong(this.messageThreadId);
			if (this.name == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nameTmp = this.name.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nameTmp.length);
				output.write(nameTmp);
			}
			if (this.icon == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.icon.serialize(output);
			}
			output.writeInt(this.creationDate);
			if (this.creatorId == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.creatorId.serialize(output);
			}
			output.writeBoolean(this.isGeneral);
			output.writeBoolean(this.isOutgoing);
			output.writeBoolean(this.isClosed);
			output.writeBoolean(this.isHidden);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ForumTopicInfo forumTopicInfo = (ForumTopicInfo) o;
			if (this.messageThreadId != forumTopicInfo.messageThreadId) {
				return false;
			}
			if (this.name != forumTopicInfo.name) {
				return false;
			}
			if (!Objects.equals(this.icon, forumTopicInfo.icon)) {
				return false;
			}
			if (this.creationDate != forumTopicInfo.creationDate) {
				return false;
			}
			if (!Objects.equals(this.creatorId, forumTopicInfo.creatorId)) {
				return false;
			}
			if (this.isGeneral != forumTopicInfo.isGeneral) {
				return false;
			}
			if (this.isOutgoing != forumTopicInfo.isOutgoing) {
				return false;
			}
			if (this.isClosed != forumTopicInfo.isClosed) {
				return false;
			}
			if (this.isHidden != forumTopicInfo.isHidden) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.messageThreadId);
			result = result * 31 + (this.name == null ? 0 : this.name.hashCode());
			result = result * 31 + (this.icon == null ? 0 : this.icon.hashCode());
			result = result * 31 + (this.creatorId == null ? 0 : this.creatorId.hashCode());
			return result;
		}
	}

	/**
	 * Describes a list of forum topics.
	**/
	public static final class ForumTopics extends Object {


		/**
		 * Approximate total number of forum topics found.
		**/
		public int totalCount;

		/**
		 * List of forum topics.
		**/
		public ForumTopic[] topics;

		/**
		 * Offset date for the next getForumTopics request.
		**/
		public int nextOffsetDate;

		/**
		 * Offset message identifier for the next getForumTopics request.
		**/
		public long nextOffsetMessageId;

		/**
		 * Offset message thread identifier for the next getForumTopics request.
		**/
		public long nextOffsetMessageThreadId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 732819537;

		/**
		 * Describes a list of forum topics.
		**/
		public ForumTopics() {}

		/**
		 * Describes a list of forum topics.
		 *
		 * @param totalCount Approximate total number of forum topics found.
		 * @param topics List of forum topics.
		 * @param nextOffsetDate Offset date for the next getForumTopics request.
		 * @param nextOffsetMessageId Offset message identifier for the next getForumTopics request.
		 * @param nextOffsetMessageThreadId Offset message thread identifier for the next getForumTopics request.
		**/
		public ForumTopics(int totalCount,
				ForumTopic[] topics,
				int nextOffsetDate,
				long nextOffsetMessageId,
				long nextOffsetMessageThreadId) {
			this.totalCount = totalCount;
			this.topics = topics;
			this.nextOffsetDate = nextOffsetDate;
			this.nextOffsetMessageId = nextOffsetMessageId;
			this.nextOffsetMessageThreadId = nextOffsetMessageThreadId;
		}

		/**
		 * Describes a list of forum topics.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ForumTopics(DataInput input) throws IOException {
			this.totalCount = input.readInt();
			if (input.readBoolean()) {
				this.topics = new ForumTopic[input.readInt()];
				for (int i = 0; i < this.topics.length; i++) {
					if (ForumTopic.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.topics[i] = new ForumTopic(input);
				}
			}
			this.nextOffsetDate = input.readInt();
			this.nextOffsetMessageId = input.readLong();
			this.nextOffsetMessageThreadId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ForumTopics.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ForumTopics.CONSTRUCTOR);
			output.writeInt(this.totalCount);
			if (this.topics == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.topics.length);
				for (int i = 0; i < this.topics.length; i++) {
					this.topics[i].serialize(output);
				}
			}
			output.writeInt(this.nextOffsetDate);
			output.writeLong(this.nextOffsetMessageId);
			output.writeLong(this.nextOffsetMessageThreadId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ForumTopics forumTopics = (ForumTopics) o;
			if (this.totalCount != forumTopics.totalCount) {
				return false;
			}
			if (!Arrays.equals(this.topics, forumTopics.topics)) {
				return false;
			}
			if (this.nextOffsetDate != forumTopics.nextOffsetDate) {
				return false;
			}
			if (this.nextOffsetMessageId != forumTopics.nextOffsetMessageId) {
				return false;
			}
			if (this.nextOffsetMessageThreadId != forumTopics.nextOffsetMessageThreadId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.totalCount);
			result = result * 31 + (Arrays.hashCode(this.topics));
			return result;
		}
	}

	/**
	 * Contains a list of messages found by a search in a given chat.
	**/
	public static final class FoundChatMessages extends Object {


		/**
		 * Approximate total number of messages found; -1 if unknown.
		**/
		public int totalCount;

		/**
		 * List of messages.
		**/
		public Message[] messages;

		/**
		 * The offset for the next request. If 0, there are no more results.
		**/
		public long nextFromMessageId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 427484196;

		/**
		 * Contains a list of messages found by a search in a given chat.
		**/
		public FoundChatMessages() {}

		/**
		 * Contains a list of messages found by a search in a given chat.
		 *
		 * @param totalCount Approximate total number of messages found; -1 if unknown.
		 * @param messages List of messages.
		 * @param nextFromMessageId The offset for the next request. If 0, there are no more results.
		**/
		public FoundChatMessages(int totalCount, Message[] messages, long nextFromMessageId) {
			this.totalCount = totalCount;
			this.messages = messages;
			this.nextFromMessageId = nextFromMessageId;
		}

		/**
		 * Contains a list of messages found by a search in a given chat.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public FoundChatMessages(DataInput input) throws IOException {
			this.totalCount = input.readInt();
			if (input.readBoolean()) {
				this.messages = new Message[input.readInt()];
				for (int i = 0; i < this.messages.length; i++) {
					if (Message.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.messages[i] = new Message(input);
				}
			}
			this.nextFromMessageId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return FoundChatMessages.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(FoundChatMessages.CONSTRUCTOR);
			output.writeInt(this.totalCount);
			if (this.messages == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.messages.length);
				for (int i = 0; i < this.messages.length; i++) {
					this.messages[i].serialize(output);
				}
			}
			output.writeLong(this.nextFromMessageId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			FoundChatMessages foundChatMessages = (FoundChatMessages) o;
			if (this.totalCount != foundChatMessages.totalCount) {
				return false;
			}
			if (!Arrays.equals(this.messages, foundChatMessages.messages)) {
				return false;
			}
			if (this.nextFromMessageId != foundChatMessages.nextFromMessageId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.totalCount);
			result = result * 31 + (Arrays.hashCode(this.messages));
			return result;
		}
	}

	/**
	 * Contains a list of downloaded files, found by a search.
	**/
	public static final class FoundFileDownloads extends Object {


		/**
		 * Total number of suitable files, ignoring offset.
		**/
		public DownloadedFileCounts totalCounts;

		/**
		 * The list of files.
		**/
		public FileDownload[] files;

		/**
		 * The offset for the next request. If empty, there are no more results.
		**/
		public String nextOffset;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1395890392;

		/**
		 * Contains a list of downloaded files, found by a search.
		**/
		public FoundFileDownloads() {}

		/**
		 * Contains a list of downloaded files, found by a search.
		 *
		 * @param totalCounts Total number of suitable files, ignoring offset.
		 * @param files The list of files.
		 * @param nextOffset The offset for the next request. If empty, there are no more results.
		**/
		public FoundFileDownloads(DownloadedFileCounts totalCounts,
				FileDownload[] files,
				String nextOffset) {
			this.totalCounts = totalCounts;
			this.files = files;
			this.nextOffset = nextOffset;
		}

		/**
		 * Contains a list of downloaded files, found by a search.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public FoundFileDownloads(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (DownloadedFileCounts.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.totalCounts = new DownloadedFileCounts(input);
			}
			if (input.readBoolean()) {
				this.files = new FileDownload[input.readInt()];
				for (int i = 0; i < this.files.length; i++) {
					if (FileDownload.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.files[i] = new FileDownload(input);
				}
			}
			if (input.readBoolean()) {
				byte[] nextOffsetTmp = new byte[input.readInt()];
				input.readFully(nextOffsetTmp);
				this.nextOffset = new String(nextOffsetTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return FoundFileDownloads.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(FoundFileDownloads.CONSTRUCTOR);
			if (this.totalCounts == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.totalCounts.serialize(output);
			}
			if (this.files == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.files.length);
				for (int i = 0; i < this.files.length; i++) {
					this.files[i].serialize(output);
				}
			}
			if (this.nextOffset == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nextOffsetTmp = this.nextOffset.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nextOffsetTmp.length);
				output.write(nextOffsetTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			FoundFileDownloads foundFileDownloads = (FoundFileDownloads) o;
			if (!Objects.equals(this.totalCounts, foundFileDownloads.totalCounts)) {
				return false;
			}
			if (!Arrays.equals(this.files, foundFileDownloads.files)) {
				return false;
			}
			if (this.nextOffset != foundFileDownloads.nextOffset) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.totalCounts == null ? 0 : this.totalCounts.hashCode();
			result = result * 31 + (Arrays.hashCode(this.files));
			result = result * 31 + (this.nextOffset == null ? 0 : this.nextOffset.hashCode());
			return result;
		}
	}

	/**
	 * Contains a list of messages found by a search.
	**/
	public static final class FoundMessages extends Object {


		/**
		 * Approximate total number of messages found; -1 if unknown.
		**/
		public int totalCount;

		/**
		 * List of messages.
		**/
		public Message[] messages;

		/**
		 * The offset for the next request. If empty, there are no more results.
		**/
		public String nextOffset;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -529809608;

		/**
		 * Contains a list of messages found by a search.
		**/
		public FoundMessages() {}

		/**
		 * Contains a list of messages found by a search.
		 *
		 * @param totalCount Approximate total number of messages found; -1 if unknown.
		 * @param messages List of messages.
		 * @param nextOffset The offset for the next request. If empty, there are no more results.
		**/
		public FoundMessages(int totalCount, Message[] messages, String nextOffset) {
			this.totalCount = totalCount;
			this.messages = messages;
			this.nextOffset = nextOffset;
		}

		/**
		 * Contains a list of messages found by a search.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public FoundMessages(DataInput input) throws IOException {
			this.totalCount = input.readInt();
			if (input.readBoolean()) {
				this.messages = new Message[input.readInt()];
				for (int i = 0; i < this.messages.length; i++) {
					if (Message.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.messages[i] = new Message(input);
				}
			}
			if (input.readBoolean()) {
				byte[] nextOffsetTmp = new byte[input.readInt()];
				input.readFully(nextOffsetTmp);
				this.nextOffset = new String(nextOffsetTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return FoundMessages.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(FoundMessages.CONSTRUCTOR);
			output.writeInt(this.totalCount);
			if (this.messages == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.messages.length);
				for (int i = 0; i < this.messages.length; i++) {
					this.messages[i].serialize(output);
				}
			}
			if (this.nextOffset == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nextOffsetTmp = this.nextOffset.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nextOffsetTmp.length);
				output.write(nextOffsetTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			FoundMessages foundMessages = (FoundMessages) o;
			if (this.totalCount != foundMessages.totalCount) {
				return false;
			}
			if (!Arrays.equals(this.messages, foundMessages.messages)) {
				return false;
			}
			if (this.nextOffset != foundMessages.nextOffset) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.totalCount);
			result = result * 31 + (Arrays.hashCode(this.messages));
			result = result * 31 + (this.nextOffset == null ? 0 : this.nextOffset.hashCode());
			return result;
		}
	}

	/**
	 * Contains information about a Web App found by its short name.
	**/
	public static final class FoundWebApp extends Object {


		/**
		 * The Web App.
		**/
		public WebApp webApp;

		/**
		 * True, if the user must be asked for the permission to the bot to send them messages.
		**/
		public boolean requestWriteAccess;

		/**
		 * True, if there is no need to show an ordinary open URL confirmation before opening the Web App. The field must be ignored and confirmation must be shown anyway if the Web App link was hidden.
		**/
		public boolean skipConfirmation;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -290926562;

		/**
		 * Contains information about a Web App found by its short name.
		**/
		public FoundWebApp() {}

		/**
		 * Contains information about a Web App found by its short name.
		 *
		 * @param webApp The Web App.
		 * @param requestWriteAccess True, if the user must be asked for the permission to the bot to send them messages.
		 * @param skipConfirmation True, if there is no need to show an ordinary open URL confirmation before opening the Web App. The field must be ignored and confirmation must be shown anyway if the Web App link was hidden.
		**/
		public FoundWebApp(WebApp webApp,
				boolean requestWriteAccess,
				boolean skipConfirmation) {
			this.webApp = webApp;
			this.requestWriteAccess = requestWriteAccess;
			this.skipConfirmation = skipConfirmation;
		}

		/**
		 * Contains information about a Web App found by its short name.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public FoundWebApp(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (WebApp.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.webApp = new WebApp(input);
			}
			this.requestWriteAccess = input.readBoolean();
			this.skipConfirmation = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return FoundWebApp.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(FoundWebApp.CONSTRUCTOR);
			if (this.webApp == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.webApp.serialize(output);
			}
			output.writeBoolean(this.requestWriteAccess);
			output.writeBoolean(this.skipConfirmation);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			FoundWebApp foundWebApp = (FoundWebApp) o;
			if (!Objects.equals(this.webApp, foundWebApp.webApp)) {
				return false;
			}
			if (this.requestWriteAccess != foundWebApp.requestWriteAccess) {
				return false;
			}
			if (this.skipConfirmation != foundWebApp.skipConfirmation) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.requestWriteAccess);
			result = result * 31 + (this.webApp == null ? 0 : this.webApp.hashCode());
			return result;
		}
	}

	/**
	 * Describes a game. Use getInternalLink with internalLinkTypeGame to
	 * share the game.
	**/
	public static final class Game extends Object {


		/**
		 * Unique game identifier.
		**/
		public long id;

		/**
		 * Game short name.
		**/
		public String shortName;

		/**
		 * Game title.
		**/
		public String title;

		/**
		 * Game text, usually containing scoreboards for a game.
		**/
		public FormattedText text;

		/**
		 * Game description.
		**/
		public String description;

		/**
		 * Game photo.
		**/
		public Photo photo;

		/**
		 * Game animation; may be null.
		**/
		public Animation animation;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1565597752;

		/**
		 * Describes a game. Use getInternalLink with internalLinkTypeGame to share the game.
		**/
		public Game() {}

		/**
		 * Describes a game. Use getInternalLink with internalLinkTypeGame to share the game.
		 *
		 * @param id Unique game identifier.
		 * @param shortName Game short name.
		 * @param title Game title.
		 * @param text Game text, usually containing scoreboards for a game.
		 * @param description Game description.
		 * @param photo Game photo.
		 * @param animation Game animation; may be null.
		**/
		public Game(long id,
				String shortName,
				String title,
				FormattedText text,
				String description,
				Photo photo,
				Animation animation) {
			this.id = id;
			this.shortName = shortName;
			this.title = title;
			this.text = text;
			this.description = description;
			this.photo = photo;
			this.animation = animation;
		}

		/**
		 * Describes a game. Use getInternalLink with internalLinkTypeGame to share the game.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public Game(DataInput input) throws IOException {
			this.id = input.readLong();
			if (input.readBoolean()) {
				byte[] shortNameTmp = new byte[input.readInt()];
				input.readFully(shortNameTmp);
				this.shortName = new String(shortNameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (FormattedText.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.text = new FormattedText(input);
			}
			if (input.readBoolean()) {
				byte[] descriptionTmp = new byte[input.readInt()];
				input.readFully(descriptionTmp);
				this.description = new String(descriptionTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (Photo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.photo = new Photo(input);
			}
			if (input.readBoolean()) {
				if (Animation.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.animation = new Animation(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return Game.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(Game.CONSTRUCTOR);
			output.writeLong(this.id);
			if (this.shortName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] shortNameTmp = this.shortName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(shortNameTmp.length);
				output.write(shortNameTmp);
			}
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
			if (this.text == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.text.serialize(output);
			}
			if (this.description == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] descriptionTmp = this.description.getBytes(StandardCharsets.UTF_8);
				output.writeInt(descriptionTmp.length);
				output.write(descriptionTmp);
			}
			if (this.photo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.photo.serialize(output);
			}
			if (this.animation == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.animation.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			Game game = (Game) o;
			if (this.id != game.id) {
				return false;
			}
			if (this.shortName != game.shortName) {
				return false;
			}
			if (this.title != game.title) {
				return false;
			}
			if (!Objects.equals(this.text, game.text)) {
				return false;
			}
			if (this.description != game.description) {
				return false;
			}
			if (!Objects.equals(this.photo, game.photo)) {
				return false;
			}
			if (!Objects.equals(this.animation, game.animation)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.id);
			result = result * 31 + (this.shortName == null ? 0 : this.shortName.hashCode());
			result = result * 31 + (this.title == null ? 0 : this.title.hashCode());
			result = result * 31 + (this.text == null ? 0 : this.text.hashCode());
			result = result * 31 + (this.description == null ? 0 : this.description.hashCode());
			result = result * 31 + (this.photo == null ? 0 : this.photo.hashCode());
			result = result * 31 + (this.animation == null ? 0 : this.animation.hashCode());
			return result;
		}
	}

	/**
	 * Contains one row of the game high score table.
	**/
	public static final class GameHighScore extends Object {


		/**
		 * Position in the high score table.
		**/
		public int position;

		/**
		 * User identifier.
		**/
		public long userId;

		/**
		 * User score.
		**/
		public int score;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 342871838;

		/**
		 * Contains one row of the game high score table.
		**/
		public GameHighScore() {}

		/**
		 * Contains one row of the game high score table.
		 *
		 * @param position Position in the high score table.
		 * @param userId User identifier.
		 * @param score User score.
		**/
		public GameHighScore(int position, long userId, int score) {
			this.position = position;
			this.userId = userId;
			this.score = score;
		}

		/**
		 * Contains one row of the game high score table.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GameHighScore(DataInput input) throws IOException {
			this.position = input.readInt();
			this.userId = input.readLong();
			this.score = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GameHighScore.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GameHighScore.CONSTRUCTOR);
			output.writeInt(this.position);
			output.writeLong(this.userId);
			output.writeInt(this.score);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GameHighScore gameHighScore = (GameHighScore) o;
			if (this.position != gameHighScore.position) {
				return false;
			}
			if (this.userId != gameHighScore.userId) {
				return false;
			}
			if (this.score != gameHighScore.score) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.position);
			return result;
		}
	}

	/**
	 * Contains a list of game high scores.
	**/
	public static final class GameHighScores extends Object {


		/**
		 * A list of game high scores.
		**/
		public GameHighScore[] scores;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -725770727;

		/**
		 * Contains a list of game high scores.
		**/
		public GameHighScores() {}

		/**
		 * Contains a list of game high scores.
		 *
		 * @param scores A list of game high scores.
		**/
		public GameHighScores(GameHighScore[] scores) {
			this.scores = scores;
		}

		/**
		 * Contains a list of game high scores.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GameHighScores(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.scores = new GameHighScore[input.readInt()];
				for (int i = 0; i < this.scores.length; i++) {
					if (GameHighScore.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.scores[i] = new GameHighScore(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GameHighScores.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GameHighScores.CONSTRUCTOR);
			if (this.scores == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.scores.length);
				for (int i = 0; i < this.scores.length; i++) {
					this.scores[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GameHighScores gameHighScores = (GameHighScores) o;
			if (!Arrays.equals(this.scores, gameHighScores.scores)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.scores);
		}
	}

	/**
	 * Describes a group call.
	**/
	public static final class GroupCall extends Object {


		/**
		 * Group call identifier.
		**/
		public int id;

		/**
		 * Group call title.
		**/
		public String title;

		/**
		 * Point in time (Unix timestamp) when the group call is supposed to be started by an administrator; 0 if it is already active or was ended.
		**/
		public int scheduledStartDate;

		/**
		 * True, if the group call is scheduled and the current user will receive a notification when the group call will start.
		**/
		public boolean enabledStartNotification;

		/**
		 * True, if the call is active.
		**/
		public boolean isActive;

		/**
		 * True, if the chat is an RTMP stream instead of an ordinary video chat.
		**/
		public boolean isRtmpStream;

		/**
		 * True, if the call is joined.
		**/
		public boolean isJoined;

		/**
		 * True, if user was kicked from the call because of network loss and the call needs to be rejoined.
		**/
		public boolean needRejoin;

		/**
		 * True, if the current user can manage the group call.
		**/
		public boolean canBeManaged;

		/**
		 * Number of participants in the group call.
		**/
		public int participantCount;

		/**
		 * True, if group call participants, which are muted, aren&#039;t returned in participant list.
		**/
		public boolean hasHiddenListeners;

		/**
		 * True, if all group call participants are loaded.
		**/
		public boolean loadedAllParticipants;

		/**
		 * At most 3 recently speaking users in the group call.
		**/
		public GroupCallRecentSpeaker[] recentSpeakers;

		/**
		 * True, if the current user&#039;s video is enabled.
		**/
		public boolean isMyVideoEnabled;

		/**
		 * True, if the current user&#039;s video is paused.
		**/
		public boolean isMyVideoPaused;

		/**
		 * True, if the current user can broadcast video or share screen.
		**/
		public boolean canEnableVideo;

		/**
		 * True, if only group call administrators can unmute new participants.
		**/
		public boolean muteNewParticipants;

		/**
		 * True, if the current user can enable or disable muteNewParticipants setting.
		**/
		public boolean canToggleMuteNewParticipants;

		/**
		 * Duration of the ongoing group call recording, in seconds; 0 if none. An updateGroupCall update is not triggered when value of this field changes, but the same recording goes on.
		**/
		public int recordDuration;

		/**
		 * True, if a video file is being recorded for the call.
		**/
		public boolean isVideoRecorded;

		/**
		 * Call duration, in seconds; for ended calls only.
		**/
		public int duration;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -123443355;

		/**
		 * Describes a group call.
		**/
		public GroupCall() {}

		/**
		 * Describes a group call.
		 *
		 * @param id Group call identifier.
		 * @param title Group call title.
		 * @param scheduledStartDate Point in time (Unix timestamp) when the group call is supposed to be started by an administrator; 0 if it is already active or was ended.
		 * @param enabledStartNotification True, if the group call is scheduled and the current user will receive a notification when the group call will start.
		 * @param isActive True, if the call is active.
		 * @param isRtmpStream True, if the chat is an RTMP stream instead of an ordinary video chat.
		 * @param isJoined True, if the call is joined.
		 * @param needRejoin True, if user was kicked from the call because of network loss and the call needs to be rejoined.
		 * @param canBeManaged True, if the current user can manage the group call.
		 * @param participantCount Number of participants in the group call.
		 * @param hasHiddenListeners True, if group call participants, which are muted, aren&#039;t returned in participant list.
		 * @param loadedAllParticipants True, if all group call participants are loaded.
		 * @param recentSpeakers At most 3 recently speaking users in the group call.
		 * @param isMyVideoEnabled True, if the current user&#039;s video is enabled.
		 * @param isMyVideoPaused True, if the current user&#039;s video is paused.
		 * @param canEnableVideo True, if the current user can broadcast video or share screen.
		 * @param muteNewParticipants True, if only group call administrators can unmute new participants.
		 * @param canToggleMuteNewParticipants True, if the current user can enable or disable muteNewParticipants setting.
		 * @param recordDuration Duration of the ongoing group call recording, in seconds; 0 if none. An updateGroupCall update is not triggered when value of this field changes, but the same recording goes on.
		 * @param isVideoRecorded True, if a video file is being recorded for the call.
		 * @param duration Call duration, in seconds; for ended calls only.
		**/
		public GroupCall(int id,
				String title,
				int scheduledStartDate,
				boolean enabledStartNotification,
				boolean isActive,
				boolean isRtmpStream,
				boolean isJoined,
				boolean needRejoin,
				boolean canBeManaged,
				int participantCount,
				boolean hasHiddenListeners,
				boolean loadedAllParticipants,
				GroupCallRecentSpeaker[] recentSpeakers,
				boolean isMyVideoEnabled,
				boolean isMyVideoPaused,
				boolean canEnableVideo,
				boolean muteNewParticipants,
				boolean canToggleMuteNewParticipants,
				int recordDuration,
				boolean isVideoRecorded,
				int duration) {
			this.id = id;
			this.title = title;
			this.scheduledStartDate = scheduledStartDate;
			this.enabledStartNotification = enabledStartNotification;
			this.isActive = isActive;
			this.isRtmpStream = isRtmpStream;
			this.isJoined = isJoined;
			this.needRejoin = needRejoin;
			this.canBeManaged = canBeManaged;
			this.participantCount = participantCount;
			this.hasHiddenListeners = hasHiddenListeners;
			this.loadedAllParticipants = loadedAllParticipants;
			this.recentSpeakers = recentSpeakers;
			this.isMyVideoEnabled = isMyVideoEnabled;
			this.isMyVideoPaused = isMyVideoPaused;
			this.canEnableVideo = canEnableVideo;
			this.muteNewParticipants = muteNewParticipants;
			this.canToggleMuteNewParticipants = canToggleMuteNewParticipants;
			this.recordDuration = recordDuration;
			this.isVideoRecorded = isVideoRecorded;
			this.duration = duration;
		}

		/**
		 * Describes a group call.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GroupCall(DataInput input) throws IOException {
			this.id = input.readInt();
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
			this.scheduledStartDate = input.readInt();
			this.enabledStartNotification = input.readBoolean();
			this.isActive = input.readBoolean();
			this.isRtmpStream = input.readBoolean();
			this.isJoined = input.readBoolean();
			this.needRejoin = input.readBoolean();
			this.canBeManaged = input.readBoolean();
			this.participantCount = input.readInt();
			this.hasHiddenListeners = input.readBoolean();
			this.loadedAllParticipants = input.readBoolean();
			if (input.readBoolean()) {
				this.recentSpeakers = new GroupCallRecentSpeaker[input.readInt()];
				for (int i = 0; i < this.recentSpeakers.length; i++) {
					if (GroupCallRecentSpeaker.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.recentSpeakers[i] = new GroupCallRecentSpeaker(input);
				}
			}
			this.isMyVideoEnabled = input.readBoolean();
			this.isMyVideoPaused = input.readBoolean();
			this.canEnableVideo = input.readBoolean();
			this.muteNewParticipants = input.readBoolean();
			this.canToggleMuteNewParticipants = input.readBoolean();
			this.recordDuration = input.readInt();
			this.isVideoRecorded = input.readBoolean();
			this.duration = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GroupCall.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GroupCall.CONSTRUCTOR);
			output.writeInt(this.id);
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
			output.writeInt(this.scheduledStartDate);
			output.writeBoolean(this.enabledStartNotification);
			output.writeBoolean(this.isActive);
			output.writeBoolean(this.isRtmpStream);
			output.writeBoolean(this.isJoined);
			output.writeBoolean(this.needRejoin);
			output.writeBoolean(this.canBeManaged);
			output.writeInt(this.participantCount);
			output.writeBoolean(this.hasHiddenListeners);
			output.writeBoolean(this.loadedAllParticipants);
			if (this.recentSpeakers == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.recentSpeakers.length);
				for (int i = 0; i < this.recentSpeakers.length; i++) {
					this.recentSpeakers[i].serialize(output);
				}
			}
			output.writeBoolean(this.isMyVideoEnabled);
			output.writeBoolean(this.isMyVideoPaused);
			output.writeBoolean(this.canEnableVideo);
			output.writeBoolean(this.muteNewParticipants);
			output.writeBoolean(this.canToggleMuteNewParticipants);
			output.writeInt(this.recordDuration);
			output.writeBoolean(this.isVideoRecorded);
			output.writeInt(this.duration);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GroupCall groupCall = (GroupCall) o;
			if (this.id != groupCall.id) {
				return false;
			}
			if (this.title != groupCall.title) {
				return false;
			}
			if (this.scheduledStartDate != groupCall.scheduledStartDate) {
				return false;
			}
			if (this.enabledStartNotification != groupCall.enabledStartNotification) {
				return false;
			}
			if (this.isActive != groupCall.isActive) {
				return false;
			}
			if (this.isRtmpStream != groupCall.isRtmpStream) {
				return false;
			}
			if (this.isJoined != groupCall.isJoined) {
				return false;
			}
			if (this.needRejoin != groupCall.needRejoin) {
				return false;
			}
			if (this.canBeManaged != groupCall.canBeManaged) {
				return false;
			}
			if (this.participantCount != groupCall.participantCount) {
				return false;
			}
			if (this.hasHiddenListeners != groupCall.hasHiddenListeners) {
				return false;
			}
			if (this.loadedAllParticipants != groupCall.loadedAllParticipants) {
				return false;
			}
			if (!Arrays.equals(this.recentSpeakers, groupCall.recentSpeakers)) {
				return false;
			}
			if (this.isMyVideoEnabled != groupCall.isMyVideoEnabled) {
				return false;
			}
			if (this.isMyVideoPaused != groupCall.isMyVideoPaused) {
				return false;
			}
			if (this.canEnableVideo != groupCall.canEnableVideo) {
				return false;
			}
			if (this.muteNewParticipants != groupCall.muteNewParticipants) {
				return false;
			}
			if (this.canToggleMuteNewParticipants != groupCall.canToggleMuteNewParticipants) {
				return false;
			}
			if (this.recordDuration != groupCall.recordDuration) {
				return false;
			}
			if (this.isVideoRecorded != groupCall.isVideoRecorded) {
				return false;
			}
			if (this.duration != groupCall.duration) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.id);
			result = result * 31 + (this.title == null ? 0 : this.title.hashCode());
			result = result * 31 + (Arrays.hashCode(this.recentSpeakers));
			return result;
		}
	}

	/**
	 * Contains the group call identifier.
	**/
	public static final class GroupCallId extends Object {


		/**
		 * Group call identifier.
		**/
		public int id;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 350534469;

		/**
		 * Contains the group call identifier.
		**/
		public GroupCallId() {}

		/**
		 * Contains the group call identifier.
		 *
		 * @param id Group call identifier.
		**/
		public GroupCallId(int id) {
			this.id = id;
		}

		/**
		 * Contains the group call identifier.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GroupCallId(DataInput input) throws IOException {
			this.id = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GroupCallId.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GroupCallId.CONSTRUCTOR);
			output.writeInt(this.id);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GroupCallId groupCallId = (GroupCallId) o;
			if (this.id != groupCallId.id) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.id);
		}
	}

	/**
	 * Represents a group call participant.
	**/
	public static final class GroupCallParticipant extends Object {


		/**
		 * Identifier of the group call participant.
		**/
		public MessageSender participantId;

		/**
		 * User&#039;s audio channel synchronization source identifier.
		**/
		public int audioSourceId;

		/**
		 * User&#039;s screen sharing audio channel synchronization source identifier.
		**/
		public int screenSharingAudioSourceId;

		/**
		 * Information about user&#039;s video channel; may be null if there is no active video.
		**/
		public GroupCallParticipantVideoInfo videoInfo;

		/**
		 * Information about user&#039;s screen sharing video channel; may be null if there is no active screen sharing video.
		**/
		public GroupCallParticipantVideoInfo screenSharingVideoInfo;

		/**
		 * The participant user&#039;s bio or the participant chat&#039;s description.
		**/
		public String bio;

		/**
		 * True, if the participant is the current user.
		**/
		public boolean isCurrentUser;

		/**
		 * True, if the participant is speaking as set by setGroupCallParticipantIsSpeaking.
		**/
		public boolean isSpeaking;

		/**
		 * True, if the participant hand is raised.
		**/
		public boolean isHandRaised;

		/**
		 * True, if the current user can mute the participant for all other group call participants.
		**/
		public boolean canBeMutedForAllUsers;

		/**
		 * True, if the current user can allow the participant to unmute themselves or unmute the participant (if the participant is the current user).
		**/
		public boolean canBeUnmutedForAllUsers;

		/**
		 * True, if the current user can mute the participant only for self.
		**/
		public boolean canBeMutedForCurrentUser;

		/**
		 * True, if the current user can unmute the participant for self.
		**/
		public boolean canBeUnmutedForCurrentUser;

		/**
		 * True, if the participant is muted for all users.
		**/
		public boolean isMutedForAllUsers;

		/**
		 * True, if the participant is muted for the current user.
		**/
		public boolean isMutedForCurrentUser;

		/**
		 * True, if the participant is muted for all users, but can unmute themselves.
		**/
		public boolean canUnmuteSelf;

		/**
		 * Participant&#039;s volume level; 1-20000 in hundreds of percents.
		**/
		public int volumeLevel;

		/**
		 * User&#039;s order in the group call participant list. Orders must be compared lexicographically. The bigger is order, the higher is user in the list. If order is empty, the user must be removed from the participant list.
		**/
		public String order;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2059182571;

		/**
		 * Represents a group call participant.
		**/
		public GroupCallParticipant() {}

		/**
		 * Represents a group call participant.
		 *
		 * @param participantId Identifier of the group call participant.
		 * @param audioSourceId User&#039;s audio channel synchronization source identifier.
		 * @param screenSharingAudioSourceId User&#039;s screen sharing audio channel synchronization source identifier.
		 * @param videoInfo Information about user&#039;s video channel; may be null if there is no active video.
		 * @param screenSharingVideoInfo Information about user&#039;s screen sharing video channel; may be null if there is no active screen sharing video.
		 * @param bio The participant user&#039;s bio or the participant chat&#039;s description.
		 * @param isCurrentUser True, if the participant is the current user.
		 * @param isSpeaking True, if the participant is speaking as set by setGroupCallParticipantIsSpeaking.
		 * @param isHandRaised True, if the participant hand is raised.
		 * @param canBeMutedForAllUsers True, if the current user can mute the participant for all other group call participants.
		 * @param canBeUnmutedForAllUsers True, if the current user can allow the participant to unmute themselves or unmute the participant (if the participant is the current user).
		 * @param canBeMutedForCurrentUser True, if the current user can mute the participant only for self.
		 * @param canBeUnmutedForCurrentUser True, if the current user can unmute the participant for self.
		 * @param isMutedForAllUsers True, if the participant is muted for all users.
		 * @param isMutedForCurrentUser True, if the participant is muted for the current user.
		 * @param canUnmuteSelf True, if the participant is muted for all users, but can unmute themselves.
		 * @param volumeLevel Participant&#039;s volume level; 1-20000 in hundreds of percents.
		 * @param order User&#039;s order in the group call participant list. Orders must be compared lexicographically. The bigger is order, the higher is user in the list. If order is empty, the user must be removed from the participant list.
		**/
		public GroupCallParticipant(MessageSender participantId,
				int audioSourceId,
				int screenSharingAudioSourceId,
				GroupCallParticipantVideoInfo videoInfo,
				GroupCallParticipantVideoInfo screenSharingVideoInfo,
				String bio,
				boolean isCurrentUser,
				boolean isSpeaking,
				boolean isHandRaised,
				boolean canBeMutedForAllUsers,
				boolean canBeUnmutedForAllUsers,
				boolean canBeMutedForCurrentUser,
				boolean canBeUnmutedForCurrentUser,
				boolean isMutedForAllUsers,
				boolean isMutedForCurrentUser,
				boolean canUnmuteSelf,
				int volumeLevel,
				String order) {
			this.participantId = participantId;
			this.audioSourceId = audioSourceId;
			this.screenSharingAudioSourceId = screenSharingAudioSourceId;
			this.videoInfo = videoInfo;
			this.screenSharingVideoInfo = screenSharingVideoInfo;
			this.bio = bio;
			this.isCurrentUser = isCurrentUser;
			this.isSpeaking = isSpeaking;
			this.isHandRaised = isHandRaised;
			this.canBeMutedForAllUsers = canBeMutedForAllUsers;
			this.canBeUnmutedForAllUsers = canBeUnmutedForAllUsers;
			this.canBeMutedForCurrentUser = canBeMutedForCurrentUser;
			this.canBeUnmutedForCurrentUser = canBeUnmutedForCurrentUser;
			this.isMutedForAllUsers = isMutedForAllUsers;
			this.isMutedForCurrentUser = isMutedForCurrentUser;
			this.canUnmuteSelf = canUnmuteSelf;
			this.volumeLevel = volumeLevel;
			this.order = order;
		}

		/**
		 * Represents a group call participant.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GroupCallParticipant(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case MessageSenderUser.CONSTRUCTOR: this.participantId = new MessageSenderUser(input); break;
					case MessageSenderChat.CONSTRUCTOR: this.participantId = new MessageSenderChat(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.audioSourceId = input.readInt();
			this.screenSharingAudioSourceId = input.readInt();
			if (input.readBoolean()) {
				if (GroupCallParticipantVideoInfo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.videoInfo = new GroupCallParticipantVideoInfo(input);
			}
			if (input.readBoolean()) {
				if (GroupCallParticipantVideoInfo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.screenSharingVideoInfo = new GroupCallParticipantVideoInfo(input);
			}
			if (input.readBoolean()) {
				byte[] bioTmp = new byte[input.readInt()];
				input.readFully(bioTmp);
				this.bio = new String(bioTmp, StandardCharsets.UTF_8);
			}
			this.isCurrentUser = input.readBoolean();
			this.isSpeaking = input.readBoolean();
			this.isHandRaised = input.readBoolean();
			this.canBeMutedForAllUsers = input.readBoolean();
			this.canBeUnmutedForAllUsers = input.readBoolean();
			this.canBeMutedForCurrentUser = input.readBoolean();
			this.canBeUnmutedForCurrentUser = input.readBoolean();
			this.isMutedForAllUsers = input.readBoolean();
			this.isMutedForCurrentUser = input.readBoolean();
			this.canUnmuteSelf = input.readBoolean();
			this.volumeLevel = input.readInt();
			if (input.readBoolean()) {
				byte[] orderTmp = new byte[input.readInt()];
				input.readFully(orderTmp);
				this.order = new String(orderTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GroupCallParticipant.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GroupCallParticipant.CONSTRUCTOR);
			if (this.participantId == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.participantId.serialize(output);
			}
			output.writeInt(this.audioSourceId);
			output.writeInt(this.screenSharingAudioSourceId);
			if (this.videoInfo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.videoInfo.serialize(output);
			}
			if (this.screenSharingVideoInfo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.screenSharingVideoInfo.serialize(output);
			}
			if (this.bio == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] bioTmp = this.bio.getBytes(StandardCharsets.UTF_8);
				output.writeInt(bioTmp.length);
				output.write(bioTmp);
			}
			output.writeBoolean(this.isCurrentUser);
			output.writeBoolean(this.isSpeaking);
			output.writeBoolean(this.isHandRaised);
			output.writeBoolean(this.canBeMutedForAllUsers);
			output.writeBoolean(this.canBeUnmutedForAllUsers);
			output.writeBoolean(this.canBeMutedForCurrentUser);
			output.writeBoolean(this.canBeUnmutedForCurrentUser);
			output.writeBoolean(this.isMutedForAllUsers);
			output.writeBoolean(this.isMutedForCurrentUser);
			output.writeBoolean(this.canUnmuteSelf);
			output.writeInt(this.volumeLevel);
			if (this.order == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] orderTmp = this.order.getBytes(StandardCharsets.UTF_8);
				output.writeInt(orderTmp.length);
				output.write(orderTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GroupCallParticipant groupCallParticipant = (GroupCallParticipant) o;
			if (!Objects.equals(this.participantId, groupCallParticipant.participantId)) {
				return false;
			}
			if (this.audioSourceId != groupCallParticipant.audioSourceId) {
				return false;
			}
			if (this.screenSharingAudioSourceId != groupCallParticipant.screenSharingAudioSourceId) {
				return false;
			}
			if (!Objects.equals(this.videoInfo, groupCallParticipant.videoInfo)) {
				return false;
			}
			if (!Objects.equals(this.screenSharingVideoInfo, groupCallParticipant.screenSharingVideoInfo)) {
				return false;
			}
			if (this.bio != groupCallParticipant.bio) {
				return false;
			}
			if (this.isCurrentUser != groupCallParticipant.isCurrentUser) {
				return false;
			}
			if (this.isSpeaking != groupCallParticipant.isSpeaking) {
				return false;
			}
			if (this.isHandRaised != groupCallParticipant.isHandRaised) {
				return false;
			}
			if (this.canBeMutedForAllUsers != groupCallParticipant.canBeMutedForAllUsers) {
				return false;
			}
			if (this.canBeUnmutedForAllUsers != groupCallParticipant.canBeUnmutedForAllUsers) {
				return false;
			}
			if (this.canBeMutedForCurrentUser != groupCallParticipant.canBeMutedForCurrentUser) {
				return false;
			}
			if (this.canBeUnmutedForCurrentUser != groupCallParticipant.canBeUnmutedForCurrentUser) {
				return false;
			}
			if (this.isMutedForAllUsers != groupCallParticipant.isMutedForAllUsers) {
				return false;
			}
			if (this.isMutedForCurrentUser != groupCallParticipant.isMutedForCurrentUser) {
				return false;
			}
			if (this.canUnmuteSelf != groupCallParticipant.canUnmuteSelf) {
				return false;
			}
			if (this.volumeLevel != groupCallParticipant.volumeLevel) {
				return false;
			}
			if (this.order != groupCallParticipant.order) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.audioSourceId);
			result = result * 31 + (this.participantId == null ? 0 : this.participantId.hashCode());
			result = result * 31 + (this.videoInfo == null ? 0 : this.videoInfo.hashCode());
			result = result * 31 + (this.screenSharingVideoInfo == null ? 0 : this.screenSharingVideoInfo.hashCode());
			result = result * 31 + (this.bio == null ? 0 : this.bio.hashCode());
			result = result * 31 + (this.order == null ? 0 : this.order.hashCode());
			return result;
		}
	}

	/**
	 * Contains information about a group call participant&#039;s video
	 * channel.
	**/
	public static final class GroupCallParticipantVideoInfo extends Object {


		/**
		 * List of synchronization source groups of the video.
		**/
		public GroupCallVideoSourceGroup[] sourceGroups;

		/**
		 * Video channel endpoint identifier.
		**/
		public String endpointId;

		/**
		 * True, if the video is paused. This flag needs to be ignored, if new video frames are received.
		**/
		public boolean isPaused;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -14294645;

		/**
		 * Contains information about a group call participant&#039;s video channel.
		**/
		public GroupCallParticipantVideoInfo() {}

		/**
		 * Contains information about a group call participant&#039;s video channel.
		 *
		 * @param sourceGroups List of synchronization source groups of the video.
		 * @param endpointId Video channel endpoint identifier.
		 * @param isPaused True, if the video is paused. This flag needs to be ignored, if new video frames are received.
		**/
		public GroupCallParticipantVideoInfo(GroupCallVideoSourceGroup[] sourceGroups,
				String endpointId,
				boolean isPaused) {
			this.sourceGroups = sourceGroups;
			this.endpointId = endpointId;
			this.isPaused = isPaused;
		}

		/**
		 * Contains information about a group call participant&#039;s video channel.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GroupCallParticipantVideoInfo(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.sourceGroups = new GroupCallVideoSourceGroup[input.readInt()];
				for (int i = 0; i < this.sourceGroups.length; i++) {
					if (GroupCallVideoSourceGroup.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.sourceGroups[i] = new GroupCallVideoSourceGroup(input);
				}
			}
			if (input.readBoolean()) {
				byte[] endpointIdTmp = new byte[input.readInt()];
				input.readFully(endpointIdTmp);
				this.endpointId = new String(endpointIdTmp, StandardCharsets.UTF_8);
			}
			this.isPaused = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GroupCallParticipantVideoInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GroupCallParticipantVideoInfo.CONSTRUCTOR);
			if (this.sourceGroups == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.sourceGroups.length);
				for (int i = 0; i < this.sourceGroups.length; i++) {
					this.sourceGroups[i].serialize(output);
				}
			}
			if (this.endpointId == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] endpointIdTmp = this.endpointId.getBytes(StandardCharsets.UTF_8);
				output.writeInt(endpointIdTmp.length);
				output.write(endpointIdTmp);
			}
			output.writeBoolean(this.isPaused);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GroupCallParticipantVideoInfo groupCallParticipantVideoInfo = (GroupCallParticipantVideoInfo) o;
			if (!Arrays.equals(this.sourceGroups, groupCallParticipantVideoInfo.sourceGroups)) {
				return false;
			}
			if (this.endpointId != groupCallParticipantVideoInfo.endpointId) {
				return false;
			}
			if (this.isPaused != groupCallParticipantVideoInfo.isPaused) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isPaused);
			result = result * 31 + (Arrays.hashCode(this.sourceGroups));
			result = result * 31 + (this.endpointId == null ? 0 : this.endpointId.hashCode());
			return result;
		}
	}

	/**
	 * Describes a recently speaking participant in a group call.
	**/
	public static final class GroupCallRecentSpeaker extends Object {


		/**
		 * Group call participant identifier.
		**/
		public MessageSender participantId;

		/**
		 * True, is the user has spoken recently.
		**/
		public boolean isSpeaking;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1819519436;

		/**
		 * Describes a recently speaking participant in a group call.
		**/
		public GroupCallRecentSpeaker() {}

		/**
		 * Describes a recently speaking participant in a group call.
		 *
		 * @param participantId Group call participant identifier.
		 * @param isSpeaking True, is the user has spoken recently.
		**/
		public GroupCallRecentSpeaker(MessageSender participantId, boolean isSpeaking) {
			this.participantId = participantId;
			this.isSpeaking = isSpeaking;
		}

		/**
		 * Describes a recently speaking participant in a group call.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GroupCallRecentSpeaker(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case MessageSenderUser.CONSTRUCTOR: this.participantId = new MessageSenderUser(input); break;
					case MessageSenderChat.CONSTRUCTOR: this.participantId = new MessageSenderChat(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.isSpeaking = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GroupCallRecentSpeaker.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GroupCallRecentSpeaker.CONSTRUCTOR);
			if (this.participantId == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.participantId.serialize(output);
			}
			output.writeBoolean(this.isSpeaking);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GroupCallRecentSpeaker groupCallRecentSpeaker = (GroupCallRecentSpeaker) o;
			if (!Objects.equals(this.participantId, groupCallRecentSpeaker.participantId)) {
				return false;
			}
			if (this.isSpeaking != groupCallRecentSpeaker.isSpeaking) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isSpeaking);
			result = result * 31 + (this.participantId == null ? 0 : this.participantId.hashCode());
			return result;
		}
	}

	/**
	 * Describes an available stream in a group call.
	**/
	public static final class GroupCallStream extends Object {


		/**
		 * Identifier of an audio/video channel.
		**/
		public int channelId;

		/**
		 * Scale of segment durations in the stream. The duration is 1000/(2**scale) milliseconds.
		**/
		public int scale;

		/**
		 * Point in time when the stream currently ends; Unix timestamp in milliseconds.
		**/
		public long timeOffset;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -264564795;

		/**
		 * Describes an available stream in a group call.
		**/
		public GroupCallStream() {}

		/**
		 * Describes an available stream in a group call.
		 *
		 * @param channelId Identifier of an audio/video channel.
		 * @param scale Scale of segment durations in the stream. The duration is 1000/(2**scale) milliseconds.
		 * @param timeOffset Point in time when the stream currently ends; Unix timestamp in milliseconds.
		**/
		public GroupCallStream(int channelId, int scale, long timeOffset) {
			this.channelId = channelId;
			this.scale = scale;
			this.timeOffset = timeOffset;
		}

		/**
		 * Describes an available stream in a group call.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GroupCallStream(DataInput input) throws IOException {
			this.channelId = input.readInt();
			this.scale = input.readInt();
			this.timeOffset = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GroupCallStream.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GroupCallStream.CONSTRUCTOR);
			output.writeInt(this.channelId);
			output.writeInt(this.scale);
			output.writeLong(this.timeOffset);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GroupCallStream groupCallStream = (GroupCallStream) o;
			if (this.channelId != groupCallStream.channelId) {
				return false;
			}
			if (this.scale != groupCallStream.scale) {
				return false;
			}
			if (this.timeOffset != groupCallStream.timeOffset) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.channelId);
			return result;
		}
	}

	/**
	 * Represents a list of group call streams.
	**/
	public static final class GroupCallStreams extends Object {


		/**
		 * A list of group call streams.
		**/
		public GroupCallStream[] streams;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1032959578;

		/**
		 * Represents a list of group call streams.
		**/
		public GroupCallStreams() {}

		/**
		 * Represents a list of group call streams.
		 *
		 * @param streams A list of group call streams.
		**/
		public GroupCallStreams(GroupCallStream[] streams) {
			this.streams = streams;
		}

		/**
		 * Represents a list of group call streams.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GroupCallStreams(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.streams = new GroupCallStream[input.readInt()];
				for (int i = 0; i < this.streams.length; i++) {
					if (GroupCallStream.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.streams[i] = new GroupCallStream(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GroupCallStreams.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GroupCallStreams.CONSTRUCTOR);
			if (this.streams == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.streams.length);
				for (int i = 0; i < this.streams.length; i++) {
					this.streams[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GroupCallStreams groupCallStreams = (GroupCallStreams) o;
			if (!Arrays.equals(this.streams, groupCallStreams.streams)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.streams);
		}
	}

	/**
	 * The worst available video quality.
	**/
	public static final class GroupCallVideoQualityThumbnail extends GroupCallVideoQuality {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -379186304;

		/**
		 * The worst available video quality.
		**/
		public GroupCallVideoQualityThumbnail() {}

		/**
		 * The worst available video quality.
		 *
		**/

		/**
		 * The worst available video quality.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GroupCallVideoQualityThumbnail(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GroupCallVideoQualityThumbnail.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GroupCallVideoQualityThumbnail.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return GroupCallVideoQualityThumbnail.CONSTRUCTOR;
		}
	}

	/**
	 * The medium video quality.
	**/
	public static final class GroupCallVideoQualityMedium extends GroupCallVideoQuality {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 394968234;

		/**
		 * The medium video quality.
		**/
		public GroupCallVideoQualityMedium() {}

		/**
		 * The medium video quality.
		 *
		**/

		/**
		 * The medium video quality.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GroupCallVideoQualityMedium(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GroupCallVideoQualityMedium.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GroupCallVideoQualityMedium.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return GroupCallVideoQualityMedium.CONSTRUCTOR;
		}
	}

	/**
	 * The best available video quality.
	**/
	public static final class GroupCallVideoQualityFull extends GroupCallVideoQuality {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2125916617;

		/**
		 * The best available video quality.
		**/
		public GroupCallVideoQualityFull() {}

		/**
		 * The best available video quality.
		 *
		**/

		/**
		 * The best available video quality.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GroupCallVideoQualityFull(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GroupCallVideoQualityFull.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GroupCallVideoQualityFull.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return GroupCallVideoQualityFull.CONSTRUCTOR;
		}
	}

	/**
	 * Describes a group of video synchronization source identifiers.
	**/
	public static final class GroupCallVideoSourceGroup extends Object {


		/**
		 * The semantics of sources, one of &quot;SIM&quot; or &quot;FID&quot;.
		**/
		public String semantics;

		/**
		 * The list of synchronization source identifiers.
		**/
		public int[] sourceIds;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1190900785;

		/**
		 * Describes a group of video synchronization source identifiers.
		**/
		public GroupCallVideoSourceGroup() {}

		/**
		 * Describes a group of video synchronization source identifiers.
		 *
		 * @param semantics The semantics of sources, one of &quot;SIM&quot; or &quot;FID&quot;.
		 * @param sourceIds The list of synchronization source identifiers.
		**/
		public GroupCallVideoSourceGroup(String semantics, int[] sourceIds) {
			this.semantics = semantics;
			this.sourceIds = sourceIds;
		}

		/**
		 * Describes a group of video synchronization source identifiers.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GroupCallVideoSourceGroup(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] semanticsTmp = new byte[input.readInt()];
				input.readFully(semanticsTmp);
				this.semantics = new String(semanticsTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				this.sourceIds = new int[input.readInt()];
				for (int i = 0; i < this.sourceIds.length; i++) {
					this.sourceIds[i] = input.readInt();
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GroupCallVideoSourceGroup.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GroupCallVideoSourceGroup.CONSTRUCTOR);
			if (this.semantics == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] semanticsTmp = this.semantics.getBytes(StandardCharsets.UTF_8);
				output.writeInt(semanticsTmp.length);
				output.write(semanticsTmp);
			}
			if (this.sourceIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.sourceIds.length);
				for (int i = 0; i < this.sourceIds.length; i++) {
					output.writeInt(this.sourceIds[i]);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GroupCallVideoSourceGroup groupCallVideoSourceGroup = (GroupCallVideoSourceGroup) o;
			if (this.semantics != groupCallVideoSourceGroup.semantics) {
				return false;
			}
			if (!Arrays.equals(this.sourceIds, groupCallVideoSourceGroup.sourceIds)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.semantics == null ? 0 : this.semantics.hashCode();
			result = result * 31 + (Arrays.hashCode(this.sourceIds));
			return result;
		}
	}

	/**
	 * Contains a list of hashtags.
	**/
	public static final class Hashtags extends Object {


		/**
		 * A list of hashtags.
		**/
		public String[] hashtags;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 676798885;

		/**
		 * Contains a list of hashtags.
		**/
		public Hashtags() {}

		/**
		 * Contains a list of hashtags.
		 *
		 * @param hashtags A list of hashtags.
		**/
		public Hashtags(String[] hashtags) {
			this.hashtags = hashtags;
		}

		/**
		 * Contains a list of hashtags.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public Hashtags(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.hashtags = new String[input.readInt()];
				for (int i = 0; i < this.hashtags.length; i++) {
					byte[] hashtagsTmp = new byte[input.readInt()];
					input.readFully(hashtagsTmp);
					this.hashtags[i] = new String(hashtagsTmp, StandardCharsets.UTF_8);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return Hashtags.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(Hashtags.CONSTRUCTOR);
			if (this.hashtags == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.hashtags.length);
				for (int i = 0; i < this.hashtags.length; i++) {
					byte[] hashtagsTmp = this.hashtags[i].getBytes(StandardCharsets.UTF_8);
					output.writeInt(hashtagsTmp.length);
					output.write(hashtagsTmp);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			Hashtags hashtags = (Hashtags) o;
			if (!Arrays.equals(this.hashtags, hashtags.hashtags)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.hashtags);
		}
	}

	/**
	 * Contains an HTTP URL.
	**/
	public static final class HttpUrl extends Object {


		/**
		 * The URL.
		**/
		public String url;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2018019930;

		/**
		 * Contains an HTTP URL.
		**/
		public HttpUrl() {}

		/**
		 * Contains an HTTP URL.
		 *
		 * @param url The URL.
		**/
		public HttpUrl(String url) {
			this.url = url;
		}

		/**
		 * Contains an HTTP URL.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public HttpUrl(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] urlTmp = new byte[input.readInt()];
				input.readFully(urlTmp);
				this.url = new String(urlTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return HttpUrl.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(HttpUrl.CONSTRUCTOR);
			if (this.url == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] urlTmp = this.url.getBytes(StandardCharsets.UTF_8);
				output.writeInt(urlTmp.length);
				output.write(urlTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			HttpUrl httpUrl = (HttpUrl) o;
			if (this.url != httpUrl.url) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.url == null ? 0 : this.url.hashCode();
		}
	}

	/**
	 * An identity document.
	**/
	public static final class IdentityDocument extends Object {


		/**
		 * Document number; 1-24 characters.
		**/
		public String number;

		/**
		 * Document expiry date; may be null if not applicable.
		**/
		public Date expiryDate;

		/**
		 * Front side of the document.
		**/
		public DatedFile frontSide;

		/**
		 * Reverse side of the document; only for driver license and identity card; may be null.
		**/
		public DatedFile reverseSide;

		/**
		 * Selfie with the document; may be null.
		**/
		public DatedFile selfie;

		/**
		 * List of files containing a certified English translation of the document.
		**/
		public DatedFile[] translation;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 445952972;

		/**
		 * An identity document.
		**/
		public IdentityDocument() {}

		/**
		 * An identity document.
		 *
		 * @param number Document number; 1-24 characters.
		 * @param expiryDate Document expiry date; may be null if not applicable.
		 * @param frontSide Front side of the document.
		 * @param reverseSide Reverse side of the document; only for driver license and identity card; may be null.
		 * @param selfie Selfie with the document; may be null.
		 * @param translation List of files containing a certified English translation of the document.
		**/
		public IdentityDocument(String number,
				Date expiryDate,
				DatedFile frontSide,
				DatedFile reverseSide,
				DatedFile selfie,
				DatedFile[] translation) {
			this.number = number;
			this.expiryDate = expiryDate;
			this.frontSide = frontSide;
			this.reverseSide = reverseSide;
			this.selfie = selfie;
			this.translation = translation;
		}

		/**
		 * An identity document.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public IdentityDocument(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] numberTmp = new byte[input.readInt()];
				input.readFully(numberTmp);
				this.number = new String(numberTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (Date.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.expiryDate = new Date(input);
			}
			if (input.readBoolean()) {
				if (DatedFile.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.frontSide = new DatedFile(input);
			}
			if (input.readBoolean()) {
				if (DatedFile.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.reverseSide = new DatedFile(input);
			}
			if (input.readBoolean()) {
				if (DatedFile.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.selfie = new DatedFile(input);
			}
			if (input.readBoolean()) {
				this.translation = new DatedFile[input.readInt()];
				for (int i = 0; i < this.translation.length; i++) {
					if (DatedFile.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.translation[i] = new DatedFile(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return IdentityDocument.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(IdentityDocument.CONSTRUCTOR);
			if (this.number == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] numberTmp = this.number.getBytes(StandardCharsets.UTF_8);
				output.writeInt(numberTmp.length);
				output.write(numberTmp);
			}
			if (this.expiryDate == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.expiryDate.serialize(output);
			}
			if (this.frontSide == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.frontSide.serialize(output);
			}
			if (this.reverseSide == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.reverseSide.serialize(output);
			}
			if (this.selfie == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.selfie.serialize(output);
			}
			if (this.translation == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.translation.length);
				for (int i = 0; i < this.translation.length; i++) {
					this.translation[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			IdentityDocument identityDocument = (IdentityDocument) o;
			if (this.number != identityDocument.number) {
				return false;
			}
			if (!Objects.equals(this.expiryDate, identityDocument.expiryDate)) {
				return false;
			}
			if (!Objects.equals(this.frontSide, identityDocument.frontSide)) {
				return false;
			}
			if (!Objects.equals(this.reverseSide, identityDocument.reverseSide)) {
				return false;
			}
			if (!Objects.equals(this.selfie, identityDocument.selfie)) {
				return false;
			}
			if (!Arrays.equals(this.translation, identityDocument.translation)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.number == null ? 0 : this.number.hashCode();
			result = result * 31 + (this.expiryDate == null ? 0 : this.expiryDate.hashCode());
			result = result * 31 + (this.frontSide == null ? 0 : this.frontSide.hashCode());
			result = result * 31 + (this.reverseSide == null ? 0 : this.reverseSide.hashCode());
			result = result * 31 + (this.selfie == null ? 0 : this.selfie.hashCode());
			result = result * 31 + (Arrays.hashCode(this.translation));
			return result;
		}
	}

	/**
	 * Represents the result of an importContacts request.
	**/
	public static final class ImportedContacts extends Object {


		/**
		 * User identifiers of the imported contacts in the same order as they were specified in the request; 0 if the contact is not yet a registered user.
		**/
		public long[] userIds;

		/**
		 * The number of users that imported the corresponding contact; 0 for already registered users or if unavailable.
		**/
		public int[] importerCount;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2068432290;

		/**
		 * Represents the result of an importContacts request.
		**/
		public ImportedContacts() {}

		/**
		 * Represents the result of an importContacts request.
		 *
		 * @param userIds User identifiers of the imported contacts in the same order as they were specified in the request; 0 if the contact is not yet a registered user.
		 * @param importerCount The number of users that imported the corresponding contact; 0 for already registered users or if unavailable.
		**/
		public ImportedContacts(long[] userIds, int[] importerCount) {
			this.userIds = userIds;
			this.importerCount = importerCount;
		}

		/**
		 * Represents the result of an importContacts request.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ImportedContacts(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.userIds = new long[input.readInt()];
				for (int i = 0; i < this.userIds.length; i++) {
					this.userIds[i] = input.readLong();
				}
			}
			if (input.readBoolean()) {
				this.importerCount = new int[input.readInt()];
				for (int i = 0; i < this.importerCount.length; i++) {
					this.importerCount[i] = input.readInt();
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ImportedContacts.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ImportedContacts.CONSTRUCTOR);
			if (this.userIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.userIds.length);
				for (int i = 0; i < this.userIds.length; i++) {
					output.writeLong(this.userIds[i]);
				}
			}
			if (this.importerCount == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.importerCount.length);
				for (int i = 0; i < this.importerCount.length; i++) {
					output.writeInt(this.importerCount[i]);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ImportedContacts importedContacts = (ImportedContacts) o;
			if (!Arrays.equals(this.userIds, importedContacts.userIds)) {
				return false;
			}
			if (!Arrays.equals(this.importerCount, importedContacts.importerCount)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Arrays.hashCode(this.userIds);
			result = result * 31 + (Arrays.hashCode(this.importerCount));
			return result;
		}
	}

	/**
	 * Represents a single button in an inline keyboard.
	**/
	public static final class InlineKeyboardButton extends Object {


		/**
		 * Text of the button.
		**/
		public String text;

		/**
		 * Type of the button.
		**/
		public InlineKeyboardButtonType type;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -372105704;

		/**
		 * Represents a single button in an inline keyboard.
		**/
		public InlineKeyboardButton() {}

		/**
		 * Represents a single button in an inline keyboard.
		 *
		 * @param text Text of the button.
		 * @param type Type of the button.
		**/
		public InlineKeyboardButton(String text, InlineKeyboardButtonType type) {
			this.text = text;
			this.type = type;
		}

		/**
		 * Represents a single button in an inline keyboard.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InlineKeyboardButton(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] textTmp = new byte[input.readInt()];
				input.readFully(textTmp);
				this.text = new String(textTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InlineKeyboardButtonTypeUrl.CONSTRUCTOR: this.type = new InlineKeyboardButtonTypeUrl(input); break;
					case InlineKeyboardButtonTypeLoginUrl.CONSTRUCTOR: this.type = new InlineKeyboardButtonTypeLoginUrl(input); break;
					case InlineKeyboardButtonTypeWebApp.CONSTRUCTOR: this.type = new InlineKeyboardButtonTypeWebApp(input); break;
					case InlineKeyboardButtonTypeCallback.CONSTRUCTOR: this.type = new InlineKeyboardButtonTypeCallback(input); break;
					case InlineKeyboardButtonTypeCallbackWithPassword.CONSTRUCTOR: this.type = new InlineKeyboardButtonTypeCallbackWithPassword(input); break;
					case InlineKeyboardButtonTypeCallbackGame.CONSTRUCTOR: this.type = new InlineKeyboardButtonTypeCallbackGame(input); break;
					case InlineKeyboardButtonTypeSwitchInline.CONSTRUCTOR: this.type = new InlineKeyboardButtonTypeSwitchInline(input); break;
					case InlineKeyboardButtonTypeBuy.CONSTRUCTOR: this.type = new InlineKeyboardButtonTypeBuy(input); break;
					case InlineKeyboardButtonTypeUser.CONSTRUCTOR: this.type = new InlineKeyboardButtonTypeUser(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InlineKeyboardButton.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InlineKeyboardButton.CONSTRUCTOR);
			if (this.text == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] textTmp = this.text.getBytes(StandardCharsets.UTF_8);
				output.writeInt(textTmp.length);
				output.write(textTmp);
			}
			if (this.type == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.type.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InlineKeyboardButton inlineKeyboardButton = (InlineKeyboardButton) o;
			if (this.text != inlineKeyboardButton.text) {
				return false;
			}
			if (!Objects.equals(this.type, inlineKeyboardButton.type)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.text == null ? 0 : this.text.hashCode();
			result = result * 31 + (this.type == null ? 0 : this.type.hashCode());
			return result;
		}
	}

	/**
	 * A button that opens a specified URL.
	**/
	public static final class InlineKeyboardButtonTypeUrl extends InlineKeyboardButtonType {


		/**
		 * HTTP or tg:// URL to open.
		**/
		public String url;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1130741420;

		/**
		 * A button that opens a specified URL.
		**/
		public InlineKeyboardButtonTypeUrl() {}

		/**
		 * A button that opens a specified URL.
		 *
		 * @param url HTTP or tg:// URL to open.
		**/
		public InlineKeyboardButtonTypeUrl(String url) {
			this.url = url;
		}

		/**
		 * A button that opens a specified URL.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InlineKeyboardButtonTypeUrl(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] urlTmp = new byte[input.readInt()];
				input.readFully(urlTmp);
				this.url = new String(urlTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InlineKeyboardButtonTypeUrl.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InlineKeyboardButtonTypeUrl.CONSTRUCTOR);
			if (this.url == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] urlTmp = this.url.getBytes(StandardCharsets.UTF_8);
				output.writeInt(urlTmp.length);
				output.write(urlTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InlineKeyboardButtonTypeUrl inlineKeyboardButtonTypeUrl = (InlineKeyboardButtonTypeUrl) o;
			if (this.url != inlineKeyboardButtonTypeUrl.url) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.url == null ? 0 : this.url.hashCode();
		}
	}

	/**
	 * A button that opens a specified URL and automatically authorize the
	 * current user by calling getLoginUrlInfo.
	**/
	public static final class InlineKeyboardButtonTypeLoginUrl extends InlineKeyboardButtonType {


		/**
		 * An HTTP URL to pass to getLoginUrlInfo.
		**/
		public String url;

		/**
		 * Unique button identifier.
		**/
		public long id;

		/**
		 * If non-empty, new text of the button in forwarded messages.
		**/
		public String forwardText;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1203413081;

		/**
		 * A button that opens a specified URL and automatically authorize the current user by calling getLoginUrlInfo.
		**/
		public InlineKeyboardButtonTypeLoginUrl() {}

		/**
		 * A button that opens a specified URL and automatically authorize the current user by calling getLoginUrlInfo.
		 *
		 * @param url An HTTP URL to pass to getLoginUrlInfo.
		 * @param id Unique button identifier.
		 * @param forwardText If non-empty, new text of the button in forwarded messages.
		**/
		public InlineKeyboardButtonTypeLoginUrl(String url, long id, String forwardText) {
			this.url = url;
			this.id = id;
			this.forwardText = forwardText;
		}

		/**
		 * A button that opens a specified URL and automatically authorize the current user by calling getLoginUrlInfo.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InlineKeyboardButtonTypeLoginUrl(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] urlTmp = new byte[input.readInt()];
				input.readFully(urlTmp);
				this.url = new String(urlTmp, StandardCharsets.UTF_8);
			}
			this.id = input.readLong();
			if (input.readBoolean()) {
				byte[] forwardTextTmp = new byte[input.readInt()];
				input.readFully(forwardTextTmp);
				this.forwardText = new String(forwardTextTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InlineKeyboardButtonTypeLoginUrl.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InlineKeyboardButtonTypeLoginUrl.CONSTRUCTOR);
			if (this.url == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] urlTmp = this.url.getBytes(StandardCharsets.UTF_8);
				output.writeInt(urlTmp.length);
				output.write(urlTmp);
			}
			output.writeLong(this.id);
			if (this.forwardText == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] forwardTextTmp = this.forwardText.getBytes(StandardCharsets.UTF_8);
				output.writeInt(forwardTextTmp.length);
				output.write(forwardTextTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InlineKeyboardButtonTypeLoginUrl inlineKeyboardButtonTypeLoginUrl = (InlineKeyboardButtonTypeLoginUrl) o;
			if (this.url != inlineKeyboardButtonTypeLoginUrl.url) {
				return false;
			}
			if (this.id != inlineKeyboardButtonTypeLoginUrl.id) {
				return false;
			}
			if (this.forwardText != inlineKeyboardButtonTypeLoginUrl.forwardText) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.id);
			result = result * 31 + (this.url == null ? 0 : this.url.hashCode());
			result = result * 31 + (this.forwardText == null ? 0 : this.forwardText.hashCode());
			return result;
		}
	}

	/**
	 * A button that opens a Web App by calling openWebApp.
	**/
	public static final class InlineKeyboardButtonTypeWebApp extends InlineKeyboardButtonType {


		/**
		 * An HTTP URL to pass to openWebApp.
		**/
		public String url;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1767471672;

		/**
		 * A button that opens a Web App by calling openWebApp.
		**/
		public InlineKeyboardButtonTypeWebApp() {}

		/**
		 * A button that opens a Web App by calling openWebApp.
		 *
		 * @param url An HTTP URL to pass to openWebApp.
		**/
		public InlineKeyboardButtonTypeWebApp(String url) {
			this.url = url;
		}

		/**
		 * A button that opens a Web App by calling openWebApp.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InlineKeyboardButtonTypeWebApp(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] urlTmp = new byte[input.readInt()];
				input.readFully(urlTmp);
				this.url = new String(urlTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InlineKeyboardButtonTypeWebApp.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InlineKeyboardButtonTypeWebApp.CONSTRUCTOR);
			if (this.url == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] urlTmp = this.url.getBytes(StandardCharsets.UTF_8);
				output.writeInt(urlTmp.length);
				output.write(urlTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InlineKeyboardButtonTypeWebApp inlineKeyboardButtonTypeWebApp = (InlineKeyboardButtonTypeWebApp) o;
			if (this.url != inlineKeyboardButtonTypeWebApp.url) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.url == null ? 0 : this.url.hashCode();
		}
	}

	/**
	 * A button that sends a callback query to a bot.
	**/
	public static final class InlineKeyboardButtonTypeCallback extends InlineKeyboardButtonType {


		/**
		 * Data to be sent to the bot via a callback query.
		**/
		public byte[] data;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1127515139;

		/**
		 * A button that sends a callback query to a bot.
		**/
		public InlineKeyboardButtonTypeCallback() {}

		/**
		 * A button that sends a callback query to a bot.
		 *
		 * @param data Data to be sent to the bot via a callback query.
		**/
		public InlineKeyboardButtonTypeCallback(byte[] data) {
			this.data = data;
		}

		/**
		 * A button that sends a callback query to a bot.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InlineKeyboardButtonTypeCallback(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.data = new byte[input.readInt()];
				input.readFully(this.data);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InlineKeyboardButtonTypeCallback.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InlineKeyboardButtonTypeCallback.CONSTRUCTOR);
			if (this.data == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.data.length);
				output.write(this.data);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InlineKeyboardButtonTypeCallback inlineKeyboardButtonTypeCallback = (InlineKeyboardButtonTypeCallback) o;
			if (this.data != inlineKeyboardButtonTypeCallback.data) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.data);
		}
	}

	/**
	 * A button that asks for the 2-step verification password of the
	 * current user and then sends a callback query to a bot.
	**/
	public static final class InlineKeyboardButtonTypeCallbackWithPassword extends InlineKeyboardButtonType {


		/**
		 * Data to be sent to the bot via a callback query.
		**/
		public byte[] data;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 908018248;

		/**
		 * A button that asks for the 2-step verification password of the current user and then sends a callback query to a bot.
		**/
		public InlineKeyboardButtonTypeCallbackWithPassword() {}

		/**
		 * A button that asks for the 2-step verification password of the current user and then sends a callback query to a bot.
		 *
		 * @param data Data to be sent to the bot via a callback query.
		**/
		public InlineKeyboardButtonTypeCallbackWithPassword(byte[] data) {
			this.data = data;
		}

		/**
		 * A button that asks for the 2-step verification password of the current user and then sends a callback query to a bot.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InlineKeyboardButtonTypeCallbackWithPassword(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.data = new byte[input.readInt()];
				input.readFully(this.data);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InlineKeyboardButtonTypeCallbackWithPassword.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InlineKeyboardButtonTypeCallbackWithPassword.CONSTRUCTOR);
			if (this.data == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.data.length);
				output.write(this.data);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InlineKeyboardButtonTypeCallbackWithPassword inlineKeyboardButtonTypeCallbackWithPassword = (InlineKeyboardButtonTypeCallbackWithPassword) o;
			if (this.data != inlineKeyboardButtonTypeCallbackWithPassword.data) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.data);
		}
	}

	/**
	 * A button with a game that sends a callback query to a bot. This
	 * button must be in the first column and row of the keyboard and can be
	 * attached only to a message with content of the type messageGame.
	**/
	public static final class InlineKeyboardButtonTypeCallbackGame extends InlineKeyboardButtonType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -383429528;

		/**
		 * A button with a game that sends a callback query to a bot. This button must be in the first column and row of the keyboard and can be attached only to a message with content of the type messageGame.
		**/
		public InlineKeyboardButtonTypeCallbackGame() {}

		/**
		 * A button with a game that sends a callback query to a bot. This button must be in the first column and row of the keyboard and can be attached only to a message with content of the type messageGame.
		 *
		**/

		/**
		 * A button with a game that sends a callback query to a bot. This button must be in the first column and row of the keyboard and can be attached only to a message with content of the type messageGame.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InlineKeyboardButtonTypeCallbackGame(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InlineKeyboardButtonTypeCallbackGame.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InlineKeyboardButtonTypeCallbackGame.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return InlineKeyboardButtonTypeCallbackGame.CONSTRUCTOR;
		}
	}

	/**
	 * A button that forces an inline query to the bot to be inserted in the
	 * input field.
	**/
	public static final class InlineKeyboardButtonTypeSwitchInline extends InlineKeyboardButtonType {


		/**
		 * Inline query to be sent to the bot.
		**/
		public String query;

		/**
		 * Target chat from which to send the inline query.
		**/
		public TargetChat targetChat;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 544906485;

		/**
		 * A button that forces an inline query to the bot to be inserted in the input field.
		**/
		public InlineKeyboardButtonTypeSwitchInline() {}

		/**
		 * A button that forces an inline query to the bot to be inserted in the input field.
		 *
		 * @param query Inline query to be sent to the bot.
		 * @param targetChat Target chat from which to send the inline query.
		**/
		public InlineKeyboardButtonTypeSwitchInline(String query, TargetChat targetChat) {
			this.query = query;
			this.targetChat = targetChat;
		}

		/**
		 * A button that forces an inline query to the bot to be inserted in the input field.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InlineKeyboardButtonTypeSwitchInline(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] queryTmp = new byte[input.readInt()];
				input.readFully(queryTmp);
				this.query = new String(queryTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case TargetChatCurrent.CONSTRUCTOR: this.targetChat = new TargetChatCurrent(input); break;
					case TargetChatChosen.CONSTRUCTOR: this.targetChat = new TargetChatChosen(input); break;
					case TargetChatInternalLink.CONSTRUCTOR: this.targetChat = new TargetChatInternalLink(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InlineKeyboardButtonTypeSwitchInline.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InlineKeyboardButtonTypeSwitchInline.CONSTRUCTOR);
			if (this.query == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] queryTmp = this.query.getBytes(StandardCharsets.UTF_8);
				output.writeInt(queryTmp.length);
				output.write(queryTmp);
			}
			if (this.targetChat == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.targetChat.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InlineKeyboardButtonTypeSwitchInline inlineKeyboardButtonTypeSwitchInline = (InlineKeyboardButtonTypeSwitchInline) o;
			if (this.query != inlineKeyboardButtonTypeSwitchInline.query) {
				return false;
			}
			if (!Objects.equals(this.targetChat, inlineKeyboardButtonTypeSwitchInline.targetChat)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.query == null ? 0 : this.query.hashCode();
			result = result * 31 + (this.targetChat == null ? 0 : this.targetChat.hashCode());
			return result;
		}
	}

	/**
	 * A button to buy something. This button must be in the first column
	 * and row of the keyboard and can be attached only to a message with
	 * content of the type messageInvoice.
	**/
	public static final class InlineKeyboardButtonTypeBuy extends InlineKeyboardButtonType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1360739440;

		/**
		 * A button to buy something. This button must be in the first column and row of the keyboard and can be attached only to a message with content of the type messageInvoice.
		**/
		public InlineKeyboardButtonTypeBuy() {}

		/**
		 * A button to buy something. This button must be in the first column and row of the keyboard and can be attached only to a message with content of the type messageInvoice.
		 *
		**/

		/**
		 * A button to buy something. This button must be in the first column and row of the keyboard and can be attached only to a message with content of the type messageInvoice.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InlineKeyboardButtonTypeBuy(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InlineKeyboardButtonTypeBuy.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InlineKeyboardButtonTypeBuy.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return InlineKeyboardButtonTypeBuy.CONSTRUCTOR;
		}
	}

	/**
	 * A button with a user reference to be handled in the same way as
	 * textEntityTypeMentionName entities.
	**/
	public static final class InlineKeyboardButtonTypeUser extends InlineKeyboardButtonType {


		/**
		 * User identifier.
		**/
		public long userId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1836574114;

		/**
		 * A button with a user reference to be handled in the same way as textEntityTypeMentionName entities.
		**/
		public InlineKeyboardButtonTypeUser() {}

		/**
		 * A button with a user reference to be handled in the same way as textEntityTypeMentionName entities.
		 *
		 * @param userId User identifier.
		**/
		public InlineKeyboardButtonTypeUser(long userId) {
			this.userId = userId;
		}

		/**
		 * A button with a user reference to be handled in the same way as textEntityTypeMentionName entities.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InlineKeyboardButtonTypeUser(DataInput input) throws IOException {
			this.userId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InlineKeyboardButtonTypeUser.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InlineKeyboardButtonTypeUser.CONSTRUCTOR);
			output.writeLong(this.userId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InlineKeyboardButtonTypeUser inlineKeyboardButtonTypeUser = (InlineKeyboardButtonTypeUser) o;
			if (this.userId != inlineKeyboardButtonTypeUser.userId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.userId);
		}
	}

	/**
	 * Represents a link to an article or web page.
	**/
	public static final class InlineQueryResultArticle extends InlineQueryResult {


		/**
		 * Unique identifier of the query result.
		**/
		public String id;

		/**
		 * URL of the result, if it exists.
		**/
		public String url;

		/**
		 * True, if the URL must be not shown.
		**/
		public boolean hideUrl;

		/**
		 * Title of the result.
		**/
		public String title;

		/**
		 * A short description of the result.
		**/
		public String description;

		/**
		 * Result thumbnail in JPEG format; may be null.
		**/
		public Thumbnail thumbnail;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 206340825;

		/**
		 * Represents a link to an article or web page.
		**/
		public InlineQueryResultArticle() {}

		/**
		 * Represents a link to an article or web page.
		 *
		 * @param id Unique identifier of the query result.
		 * @param url URL of the result, if it exists.
		 * @param hideUrl True, if the URL must be not shown.
		 * @param title Title of the result.
		 * @param description A short description of the result.
		 * @param thumbnail Result thumbnail in JPEG format; may be null.
		**/
		public InlineQueryResultArticle(String id,
				String url,
				boolean hideUrl,
				String title,
				String description,
				Thumbnail thumbnail) {
			this.id = id;
			this.url = url;
			this.hideUrl = hideUrl;
			this.title = title;
			this.description = description;
			this.thumbnail = thumbnail;
		}

		/**
		 * Represents a link to an article or web page.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InlineQueryResultArticle(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] idTmp = new byte[input.readInt()];
				input.readFully(idTmp);
				this.id = new String(idTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] urlTmp = new byte[input.readInt()];
				input.readFully(urlTmp);
				this.url = new String(urlTmp, StandardCharsets.UTF_8);
			}
			this.hideUrl = input.readBoolean();
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] descriptionTmp = new byte[input.readInt()];
				input.readFully(descriptionTmp);
				this.description = new String(descriptionTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (Thumbnail.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.thumbnail = new Thumbnail(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InlineQueryResultArticle.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InlineQueryResultArticle.CONSTRUCTOR);
			if (this.id == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] idTmp = this.id.getBytes(StandardCharsets.UTF_8);
				output.writeInt(idTmp.length);
				output.write(idTmp);
			}
			if (this.url == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] urlTmp = this.url.getBytes(StandardCharsets.UTF_8);
				output.writeInt(urlTmp.length);
				output.write(urlTmp);
			}
			output.writeBoolean(this.hideUrl);
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
			if (this.description == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] descriptionTmp = this.description.getBytes(StandardCharsets.UTF_8);
				output.writeInt(descriptionTmp.length);
				output.write(descriptionTmp);
			}
			if (this.thumbnail == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.thumbnail.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InlineQueryResultArticle inlineQueryResultArticle = (InlineQueryResultArticle) o;
			if (this.id != inlineQueryResultArticle.id) {
				return false;
			}
			if (this.url != inlineQueryResultArticle.url) {
				return false;
			}
			if (this.hideUrl != inlineQueryResultArticle.hideUrl) {
				return false;
			}
			if (this.title != inlineQueryResultArticle.title) {
				return false;
			}
			if (this.description != inlineQueryResultArticle.description) {
				return false;
			}
			if (!Objects.equals(this.thumbnail, inlineQueryResultArticle.thumbnail)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.hideUrl);
			result = result * 31 + (this.id == null ? 0 : this.id.hashCode());
			result = result * 31 + (this.url == null ? 0 : this.url.hashCode());
			result = result * 31 + (this.title == null ? 0 : this.title.hashCode());
			result = result * 31 + (this.description == null ? 0 : this.description.hashCode());
			result = result * 31 + (this.thumbnail == null ? 0 : this.thumbnail.hashCode());
			return result;
		}
	}

	/**
	 * Represents a user contact.
	**/
	public static final class InlineQueryResultContact extends InlineQueryResult {


		/**
		 * Unique identifier of the query result.
		**/
		public String id;

		/**
		 * A user contact.
		**/
		public Contact contact;

		/**
		 * Result thumbnail in JPEG format; may be null.
		**/
		public Thumbnail thumbnail;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -181960174;

		/**
		 * Represents a user contact.
		**/
		public InlineQueryResultContact() {}

		/**
		 * Represents a user contact.
		 *
		 * @param id Unique identifier of the query result.
		 * @param contact A user contact.
		 * @param thumbnail Result thumbnail in JPEG format; may be null.
		**/
		public InlineQueryResultContact(String id, Contact contact, Thumbnail thumbnail) {
			this.id = id;
			this.contact = contact;
			this.thumbnail = thumbnail;
		}

		/**
		 * Represents a user contact.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InlineQueryResultContact(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] idTmp = new byte[input.readInt()];
				input.readFully(idTmp);
				this.id = new String(idTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (Contact.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.contact = new Contact(input);
			}
			if (input.readBoolean()) {
				if (Thumbnail.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.thumbnail = new Thumbnail(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InlineQueryResultContact.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InlineQueryResultContact.CONSTRUCTOR);
			if (this.id == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] idTmp = this.id.getBytes(StandardCharsets.UTF_8);
				output.writeInt(idTmp.length);
				output.write(idTmp);
			}
			if (this.contact == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.contact.serialize(output);
			}
			if (this.thumbnail == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.thumbnail.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InlineQueryResultContact inlineQueryResultContact = (InlineQueryResultContact) o;
			if (this.id != inlineQueryResultContact.id) {
				return false;
			}
			if (!Objects.equals(this.contact, inlineQueryResultContact.contact)) {
				return false;
			}
			if (!Objects.equals(this.thumbnail, inlineQueryResultContact.thumbnail)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.id == null ? 0 : this.id.hashCode();
			result = result * 31 + (this.contact == null ? 0 : this.contact.hashCode());
			result = result * 31 + (this.thumbnail == null ? 0 : this.thumbnail.hashCode());
			return result;
		}
	}

	/**
	 * Represents a point on the map.
	**/
	public static final class InlineQueryResultLocation extends InlineQueryResult {


		/**
		 * Unique identifier of the query result.
		**/
		public String id;

		/**
		 * Location result.
		**/
		public Location location;

		/**
		 * Title of the result.
		**/
		public String title;

		/**
		 * Result thumbnail in JPEG format; may be null.
		**/
		public Thumbnail thumbnail;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 466004752;

		/**
		 * Represents a point on the map.
		**/
		public InlineQueryResultLocation() {}

		/**
		 * Represents a point on the map.
		 *
		 * @param id Unique identifier of the query result.
		 * @param location Location result.
		 * @param title Title of the result.
		 * @param thumbnail Result thumbnail in JPEG format; may be null.
		**/
		public InlineQueryResultLocation(String id,
				Location location,
				String title,
				Thumbnail thumbnail) {
			this.id = id;
			this.location = location;
			this.title = title;
			this.thumbnail = thumbnail;
		}

		/**
		 * Represents a point on the map.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InlineQueryResultLocation(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] idTmp = new byte[input.readInt()];
				input.readFully(idTmp);
				this.id = new String(idTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (Location.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.location = new Location(input);
			}
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (Thumbnail.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.thumbnail = new Thumbnail(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InlineQueryResultLocation.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InlineQueryResultLocation.CONSTRUCTOR);
			if (this.id == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] idTmp = this.id.getBytes(StandardCharsets.UTF_8);
				output.writeInt(idTmp.length);
				output.write(idTmp);
			}
			if (this.location == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.location.serialize(output);
			}
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
			if (this.thumbnail == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.thumbnail.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InlineQueryResultLocation inlineQueryResultLocation = (InlineQueryResultLocation) o;
			if (this.id != inlineQueryResultLocation.id) {
				return false;
			}
			if (!Objects.equals(this.location, inlineQueryResultLocation.location)) {
				return false;
			}
			if (this.title != inlineQueryResultLocation.title) {
				return false;
			}
			if (!Objects.equals(this.thumbnail, inlineQueryResultLocation.thumbnail)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.id == null ? 0 : this.id.hashCode();
			result = result * 31 + (this.location == null ? 0 : this.location.hashCode());
			result = result * 31 + (this.title == null ? 0 : this.title.hashCode());
			result = result * 31 + (this.thumbnail == null ? 0 : this.thumbnail.hashCode());
			return result;
		}
	}

	/**
	 * Represents information about a venue.
	**/
	public static final class InlineQueryResultVenue extends InlineQueryResult {


		/**
		 * Unique identifier of the query result.
		**/
		public String id;

		/**
		 * Venue result.
		**/
		public Venue venue;

		/**
		 * Result thumbnail in JPEG format; may be null.
		**/
		public Thumbnail thumbnail;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1281036382;

		/**
		 * Represents information about a venue.
		**/
		public InlineQueryResultVenue() {}

		/**
		 * Represents information about a venue.
		 *
		 * @param id Unique identifier of the query result.
		 * @param venue Venue result.
		 * @param thumbnail Result thumbnail in JPEG format; may be null.
		**/
		public InlineQueryResultVenue(String id, Venue venue, Thumbnail thumbnail) {
			this.id = id;
			this.venue = venue;
			this.thumbnail = thumbnail;
		}

		/**
		 * Represents information about a venue.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InlineQueryResultVenue(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] idTmp = new byte[input.readInt()];
				input.readFully(idTmp);
				this.id = new String(idTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (Venue.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.venue = new Venue(input);
			}
			if (input.readBoolean()) {
				if (Thumbnail.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.thumbnail = new Thumbnail(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InlineQueryResultVenue.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InlineQueryResultVenue.CONSTRUCTOR);
			if (this.id == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] idTmp = this.id.getBytes(StandardCharsets.UTF_8);
				output.writeInt(idTmp.length);
				output.write(idTmp);
			}
			if (this.venue == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.venue.serialize(output);
			}
			if (this.thumbnail == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.thumbnail.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InlineQueryResultVenue inlineQueryResultVenue = (InlineQueryResultVenue) o;
			if (this.id != inlineQueryResultVenue.id) {
				return false;
			}
			if (!Objects.equals(this.venue, inlineQueryResultVenue.venue)) {
				return false;
			}
			if (!Objects.equals(this.thumbnail, inlineQueryResultVenue.thumbnail)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.id == null ? 0 : this.id.hashCode();
			result = result * 31 + (this.venue == null ? 0 : this.venue.hashCode());
			result = result * 31 + (this.thumbnail == null ? 0 : this.thumbnail.hashCode());
			return result;
		}
	}

	/**
	 * Represents information about a game.
	**/
	public static final class InlineQueryResultGame extends InlineQueryResult {


		/**
		 * Unique identifier of the query result.
		**/
		public String id;

		/**
		 * Game result.
		**/
		public Game game;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1706916987;

		/**
		 * Represents information about a game.
		**/
		public InlineQueryResultGame() {}

		/**
		 * Represents information about a game.
		 *
		 * @param id Unique identifier of the query result.
		 * @param game Game result.
		**/
		public InlineQueryResultGame(String id, Game game) {
			this.id = id;
			this.game = game;
		}

		/**
		 * Represents information about a game.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InlineQueryResultGame(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] idTmp = new byte[input.readInt()];
				input.readFully(idTmp);
				this.id = new String(idTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (Game.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.game = new Game(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InlineQueryResultGame.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InlineQueryResultGame.CONSTRUCTOR);
			if (this.id == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] idTmp = this.id.getBytes(StandardCharsets.UTF_8);
				output.writeInt(idTmp.length);
				output.write(idTmp);
			}
			if (this.game == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.game.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InlineQueryResultGame inlineQueryResultGame = (InlineQueryResultGame) o;
			if (this.id != inlineQueryResultGame.id) {
				return false;
			}
			if (!Objects.equals(this.game, inlineQueryResultGame.game)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.id == null ? 0 : this.id.hashCode();
			result = result * 31 + (this.game == null ? 0 : this.game.hashCode());
			return result;
		}
	}

	/**
	 * Represents an animation file.
	**/
	public static final class InlineQueryResultAnimation extends InlineQueryResult {


		/**
		 * Unique identifier of the query result.
		**/
		public String id;

		/**
		 * Animation file.
		**/
		public Animation animation;

		/**
		 * Animation title.
		**/
		public String title;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2009984267;

		/**
		 * Represents an animation file.
		**/
		public InlineQueryResultAnimation() {}

		/**
		 * Represents an animation file.
		 *
		 * @param id Unique identifier of the query result.
		 * @param animation Animation file.
		 * @param title Animation title.
		**/
		public InlineQueryResultAnimation(String id, Animation animation, String title) {
			this.id = id;
			this.animation = animation;
			this.title = title;
		}

		/**
		 * Represents an animation file.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InlineQueryResultAnimation(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] idTmp = new byte[input.readInt()];
				input.readFully(idTmp);
				this.id = new String(idTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (Animation.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.animation = new Animation(input);
			}
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InlineQueryResultAnimation.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InlineQueryResultAnimation.CONSTRUCTOR);
			if (this.id == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] idTmp = this.id.getBytes(StandardCharsets.UTF_8);
				output.writeInt(idTmp.length);
				output.write(idTmp);
			}
			if (this.animation == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.animation.serialize(output);
			}
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InlineQueryResultAnimation inlineQueryResultAnimation = (InlineQueryResultAnimation) o;
			if (this.id != inlineQueryResultAnimation.id) {
				return false;
			}
			if (!Objects.equals(this.animation, inlineQueryResultAnimation.animation)) {
				return false;
			}
			if (this.title != inlineQueryResultAnimation.title) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.id == null ? 0 : this.id.hashCode();
			result = result * 31 + (this.animation == null ? 0 : this.animation.hashCode());
			result = result * 31 + (this.title == null ? 0 : this.title.hashCode());
			return result;
		}
	}

	/**
	 * Represents an audio file.
	**/
	public static final class InlineQueryResultAudio extends InlineQueryResult {


		/**
		 * Unique identifier of the query result.
		**/
		public String id;

		/**
		 * Audio file.
		**/
		public Audio audio;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 842650360;

		/**
		 * Represents an audio file.
		**/
		public InlineQueryResultAudio() {}

		/**
		 * Represents an audio file.
		 *
		 * @param id Unique identifier of the query result.
		 * @param audio Audio file.
		**/
		public InlineQueryResultAudio(String id, Audio audio) {
			this.id = id;
			this.audio = audio;
		}

		/**
		 * Represents an audio file.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InlineQueryResultAudio(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] idTmp = new byte[input.readInt()];
				input.readFully(idTmp);
				this.id = new String(idTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (Audio.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.audio = new Audio(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InlineQueryResultAudio.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InlineQueryResultAudio.CONSTRUCTOR);
			if (this.id == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] idTmp = this.id.getBytes(StandardCharsets.UTF_8);
				output.writeInt(idTmp.length);
				output.write(idTmp);
			}
			if (this.audio == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.audio.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InlineQueryResultAudio inlineQueryResultAudio = (InlineQueryResultAudio) o;
			if (this.id != inlineQueryResultAudio.id) {
				return false;
			}
			if (!Objects.equals(this.audio, inlineQueryResultAudio.audio)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.id == null ? 0 : this.id.hashCode();
			result = result * 31 + (this.audio == null ? 0 : this.audio.hashCode());
			return result;
		}
	}

	/**
	 * Represents a document.
	**/
	public static final class InlineQueryResultDocument extends InlineQueryResult {


		/**
		 * Unique identifier of the query result.
		**/
		public String id;

		/**
		 * Document.
		**/
		public Document document;

		/**
		 * Document title.
		**/
		public String title;

		/**
		 * Document description.
		**/
		public String description;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1491268539;

		/**
		 * Represents a document.
		**/
		public InlineQueryResultDocument() {}

		/**
		 * Represents a document.
		 *
		 * @param id Unique identifier of the query result.
		 * @param document Document.
		 * @param title Document title.
		 * @param description Document description.
		**/
		public InlineQueryResultDocument(String id,
				Document document,
				String title,
				String description) {
			this.id = id;
			this.document = document;
			this.title = title;
			this.description = description;
		}

		/**
		 * Represents a document.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InlineQueryResultDocument(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] idTmp = new byte[input.readInt()];
				input.readFully(idTmp);
				this.id = new String(idTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (Document.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.document = new Document(input);
			}
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] descriptionTmp = new byte[input.readInt()];
				input.readFully(descriptionTmp);
				this.description = new String(descriptionTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InlineQueryResultDocument.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InlineQueryResultDocument.CONSTRUCTOR);
			if (this.id == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] idTmp = this.id.getBytes(StandardCharsets.UTF_8);
				output.writeInt(idTmp.length);
				output.write(idTmp);
			}
			if (this.document == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.document.serialize(output);
			}
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
			if (this.description == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] descriptionTmp = this.description.getBytes(StandardCharsets.UTF_8);
				output.writeInt(descriptionTmp.length);
				output.write(descriptionTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InlineQueryResultDocument inlineQueryResultDocument = (InlineQueryResultDocument) o;
			if (this.id != inlineQueryResultDocument.id) {
				return false;
			}
			if (!Objects.equals(this.document, inlineQueryResultDocument.document)) {
				return false;
			}
			if (this.title != inlineQueryResultDocument.title) {
				return false;
			}
			if (this.description != inlineQueryResultDocument.description) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.id == null ? 0 : this.id.hashCode();
			result = result * 31 + (this.document == null ? 0 : this.document.hashCode());
			result = result * 31 + (this.title == null ? 0 : this.title.hashCode());
			result = result * 31 + (this.description == null ? 0 : this.description.hashCode());
			return result;
		}
	}

	/**
	 * Represents a photo.
	**/
	public static final class InlineQueryResultPhoto extends InlineQueryResult {


		/**
		 * Unique identifier of the query result.
		**/
		public String id;

		/**
		 * Photo.
		**/
		public Photo photo;

		/**
		 * Title of the result, if known.
		**/
		public String title;

		/**
		 * A short description of the result, if known.
		**/
		public String description;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1848319440;

		/**
		 * Represents a photo.
		**/
		public InlineQueryResultPhoto() {}

		/**
		 * Represents a photo.
		 *
		 * @param id Unique identifier of the query result.
		 * @param photo Photo.
		 * @param title Title of the result, if known.
		 * @param description A short description of the result, if known.
		**/
		public InlineQueryResultPhoto(String id, Photo photo, String title, String description) {
			this.id = id;
			this.photo = photo;
			this.title = title;
			this.description = description;
		}

		/**
		 * Represents a photo.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InlineQueryResultPhoto(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] idTmp = new byte[input.readInt()];
				input.readFully(idTmp);
				this.id = new String(idTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (Photo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.photo = new Photo(input);
			}
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] descriptionTmp = new byte[input.readInt()];
				input.readFully(descriptionTmp);
				this.description = new String(descriptionTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InlineQueryResultPhoto.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InlineQueryResultPhoto.CONSTRUCTOR);
			if (this.id == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] idTmp = this.id.getBytes(StandardCharsets.UTF_8);
				output.writeInt(idTmp.length);
				output.write(idTmp);
			}
			if (this.photo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.photo.serialize(output);
			}
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
			if (this.description == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] descriptionTmp = this.description.getBytes(StandardCharsets.UTF_8);
				output.writeInt(descriptionTmp.length);
				output.write(descriptionTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InlineQueryResultPhoto inlineQueryResultPhoto = (InlineQueryResultPhoto) o;
			if (this.id != inlineQueryResultPhoto.id) {
				return false;
			}
			if (!Objects.equals(this.photo, inlineQueryResultPhoto.photo)) {
				return false;
			}
			if (this.title != inlineQueryResultPhoto.title) {
				return false;
			}
			if (this.description != inlineQueryResultPhoto.description) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.id == null ? 0 : this.id.hashCode();
			result = result * 31 + (this.photo == null ? 0 : this.photo.hashCode());
			result = result * 31 + (this.title == null ? 0 : this.title.hashCode());
			result = result * 31 + (this.description == null ? 0 : this.description.hashCode());
			return result;
		}
	}

	/**
	 * Represents a sticker.
	**/
	public static final class InlineQueryResultSticker extends InlineQueryResult {


		/**
		 * Unique identifier of the query result.
		**/
		public String id;

		/**
		 * Sticker.
		**/
		public Sticker sticker;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1848224245;

		/**
		 * Represents a sticker.
		**/
		public InlineQueryResultSticker() {}

		/**
		 * Represents a sticker.
		 *
		 * @param id Unique identifier of the query result.
		 * @param sticker Sticker.
		**/
		public InlineQueryResultSticker(String id, Sticker sticker) {
			this.id = id;
			this.sticker = sticker;
		}

		/**
		 * Represents a sticker.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InlineQueryResultSticker(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] idTmp = new byte[input.readInt()];
				input.readFully(idTmp);
				this.id = new String(idTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (Sticker.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.sticker = new Sticker(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InlineQueryResultSticker.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InlineQueryResultSticker.CONSTRUCTOR);
			if (this.id == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] idTmp = this.id.getBytes(StandardCharsets.UTF_8);
				output.writeInt(idTmp.length);
				output.write(idTmp);
			}
			if (this.sticker == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.sticker.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InlineQueryResultSticker inlineQueryResultSticker = (InlineQueryResultSticker) o;
			if (this.id != inlineQueryResultSticker.id) {
				return false;
			}
			if (!Objects.equals(this.sticker, inlineQueryResultSticker.sticker)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.id == null ? 0 : this.id.hashCode();
			result = result * 31 + (this.sticker == null ? 0 : this.sticker.hashCode());
			return result;
		}
	}

	/**
	 * Represents a video.
	**/
	public static final class InlineQueryResultVideo extends InlineQueryResult {


		/**
		 * Unique identifier of the query result.
		**/
		public String id;

		/**
		 * Video.
		**/
		public Video video;

		/**
		 * Title of the video.
		**/
		public String title;

		/**
		 * Description of the video.
		**/
		public String description;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1373158683;

		/**
		 * Represents a video.
		**/
		public InlineQueryResultVideo() {}

		/**
		 * Represents a video.
		 *
		 * @param id Unique identifier of the query result.
		 * @param video Video.
		 * @param title Title of the video.
		 * @param description Description of the video.
		**/
		public InlineQueryResultVideo(String id, Video video, String title, String description) {
			this.id = id;
			this.video = video;
			this.title = title;
			this.description = description;
		}

		/**
		 * Represents a video.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InlineQueryResultVideo(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] idTmp = new byte[input.readInt()];
				input.readFully(idTmp);
				this.id = new String(idTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (Video.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.video = new Video(input);
			}
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] descriptionTmp = new byte[input.readInt()];
				input.readFully(descriptionTmp);
				this.description = new String(descriptionTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InlineQueryResultVideo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InlineQueryResultVideo.CONSTRUCTOR);
			if (this.id == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] idTmp = this.id.getBytes(StandardCharsets.UTF_8);
				output.writeInt(idTmp.length);
				output.write(idTmp);
			}
			if (this.video == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.video.serialize(output);
			}
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
			if (this.description == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] descriptionTmp = this.description.getBytes(StandardCharsets.UTF_8);
				output.writeInt(descriptionTmp.length);
				output.write(descriptionTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InlineQueryResultVideo inlineQueryResultVideo = (InlineQueryResultVideo) o;
			if (this.id != inlineQueryResultVideo.id) {
				return false;
			}
			if (!Objects.equals(this.video, inlineQueryResultVideo.video)) {
				return false;
			}
			if (this.title != inlineQueryResultVideo.title) {
				return false;
			}
			if (this.description != inlineQueryResultVideo.description) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.id == null ? 0 : this.id.hashCode();
			result = result * 31 + (this.video == null ? 0 : this.video.hashCode());
			result = result * 31 + (this.title == null ? 0 : this.title.hashCode());
			result = result * 31 + (this.description == null ? 0 : this.description.hashCode());
			return result;
		}
	}

	/**
	 * Represents a voice note.
	**/
	public static final class InlineQueryResultVoiceNote extends InlineQueryResult {


		/**
		 * Unique identifier of the query result.
		**/
		public String id;

		/**
		 * Voice note.
		**/
		public VoiceNote voiceNote;

		/**
		 * Title of the voice note.
		**/
		public String title;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1897393105;

		/**
		 * Represents a voice note.
		**/
		public InlineQueryResultVoiceNote() {}

		/**
		 * Represents a voice note.
		 *
		 * @param id Unique identifier of the query result.
		 * @param voiceNote Voice note.
		 * @param title Title of the voice note.
		**/
		public InlineQueryResultVoiceNote(String id, VoiceNote voiceNote, String title) {
			this.id = id;
			this.voiceNote = voiceNote;
			this.title = title;
		}

		/**
		 * Represents a voice note.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InlineQueryResultVoiceNote(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] idTmp = new byte[input.readInt()];
				input.readFully(idTmp);
				this.id = new String(idTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (VoiceNote.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.voiceNote = new VoiceNote(input);
			}
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InlineQueryResultVoiceNote.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InlineQueryResultVoiceNote.CONSTRUCTOR);
			if (this.id == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] idTmp = this.id.getBytes(StandardCharsets.UTF_8);
				output.writeInt(idTmp.length);
				output.write(idTmp);
			}
			if (this.voiceNote == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.voiceNote.serialize(output);
			}
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InlineQueryResultVoiceNote inlineQueryResultVoiceNote = (InlineQueryResultVoiceNote) o;
			if (this.id != inlineQueryResultVoiceNote.id) {
				return false;
			}
			if (!Objects.equals(this.voiceNote, inlineQueryResultVoiceNote.voiceNote)) {
				return false;
			}
			if (this.title != inlineQueryResultVoiceNote.title) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.id == null ? 0 : this.id.hashCode();
			result = result * 31 + (this.voiceNote == null ? 0 : this.voiceNote.hashCode());
			result = result * 31 + (this.title == null ? 0 : this.title.hashCode());
			return result;
		}
	}

	/**
	 * Represents the results of the inline query. Use
	 * sendInlineQueryResultMessage to send the result of the query.
	**/
	public static final class InlineQueryResults extends Object {


		/**
		 * Unique identifier of the inline query.
		**/
		public long inlineQueryId;

		/**
		 * Button to be shown above inline query results; may be null.
		**/
		public InlineQueryResultsButton button;

		/**
		 * Results of the query.
		**/
		public InlineQueryResult[] results;

		/**
		 * The offset for the next request. If empty, there are no more results.
		**/
		public String nextOffset;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1830685615;

		/**
		 * Represents the results of the inline query. Use sendInlineQueryResultMessage to send the result of the query.
		**/
		public InlineQueryResults() {}

		/**
		 * Represents the results of the inline query. Use sendInlineQueryResultMessage to send the result of the query.
		 *
		 * @param inlineQueryId Unique identifier of the inline query.
		 * @param button Button to be shown above inline query results; may be null.
		 * @param results Results of the query.
		 * @param nextOffset The offset for the next request. If empty, there are no more results.
		**/
		public InlineQueryResults(long inlineQueryId,
				InlineQueryResultsButton button,
				InlineQueryResult[] results,
				String nextOffset) {
			this.inlineQueryId = inlineQueryId;
			this.button = button;
			this.results = results;
			this.nextOffset = nextOffset;
		}

		/**
		 * Represents the results of the inline query. Use sendInlineQueryResultMessage to send the result of the query.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InlineQueryResults(DataInput input) throws IOException {
			this.inlineQueryId = input.readLong();
			if (input.readBoolean()) {
				if (InlineQueryResultsButton.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.button = new InlineQueryResultsButton(input);
			}
			if (input.readBoolean()) {
				this.results = new InlineQueryResult[input.readInt()];
				for (int i = 0; i < this.results.length; i++) {
					switch(input.readInt()) {
						case InlineQueryResultArticle.CONSTRUCTOR: this.results[i] = new InlineQueryResultArticle(input); break;
						case InlineQueryResultContact.CONSTRUCTOR: this.results[i] = new InlineQueryResultContact(input); break;
						case InlineQueryResultLocation.CONSTRUCTOR: this.results[i] = new InlineQueryResultLocation(input); break;
						case InlineQueryResultVenue.CONSTRUCTOR: this.results[i] = new InlineQueryResultVenue(input); break;
						case InlineQueryResultGame.CONSTRUCTOR: this.results[i] = new InlineQueryResultGame(input); break;
						case InlineQueryResultAnimation.CONSTRUCTOR: this.results[i] = new InlineQueryResultAnimation(input); break;
						case InlineQueryResultAudio.CONSTRUCTOR: this.results[i] = new InlineQueryResultAudio(input); break;
						case InlineQueryResultDocument.CONSTRUCTOR: this.results[i] = new InlineQueryResultDocument(input); break;
						case InlineQueryResultPhoto.CONSTRUCTOR: this.results[i] = new InlineQueryResultPhoto(input); break;
						case InlineQueryResultSticker.CONSTRUCTOR: this.results[i] = new InlineQueryResultSticker(input); break;
						case InlineQueryResultVideo.CONSTRUCTOR: this.results[i] = new InlineQueryResultVideo(input); break;
						case InlineQueryResultVoiceNote.CONSTRUCTOR: this.results[i] = new InlineQueryResultVoiceNote(input); break;
						default: {
							throw new UnsupportedOperationException();
						}
					}
				}
			}
			if (input.readBoolean()) {
				byte[] nextOffsetTmp = new byte[input.readInt()];
				input.readFully(nextOffsetTmp);
				this.nextOffset = new String(nextOffsetTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InlineQueryResults.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InlineQueryResults.CONSTRUCTOR);
			output.writeLong(this.inlineQueryId);
			if (this.button == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.button.serialize(output);
			}
			if (this.results == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.results.length);
				for (int i = 0; i < this.results.length; i++) {
					this.results[i].serialize(output);
				}
			}
			if (this.nextOffset == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nextOffsetTmp = this.nextOffset.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nextOffsetTmp.length);
				output.write(nextOffsetTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InlineQueryResults inlineQueryResults = (InlineQueryResults) o;
			if (this.inlineQueryId != inlineQueryResults.inlineQueryId) {
				return false;
			}
			if (!Objects.equals(this.button, inlineQueryResults.button)) {
				return false;
			}
			if (!Arrays.equals(this.results, inlineQueryResults.results)) {
				return false;
			}
			if (this.nextOffset != inlineQueryResults.nextOffset) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.inlineQueryId);
			result = result * 31 + (this.button == null ? 0 : this.button.hashCode());
			result = result * 31 + (Arrays.hashCode(this.results));
			result = result * 31 + (this.nextOffset == null ? 0 : this.nextOffset.hashCode());
			return result;
		}
	}

	/**
	 * Represents a button to be shown above inline query results.
	**/
	public static final class InlineQueryResultsButton extends Object {


		/**
		 * The text of the button.
		**/
		public String text;

		/**
		 * Type of the button.
		**/
		public InlineQueryResultsButtonType type;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -790689618;

		/**
		 * Represents a button to be shown above inline query results.
		**/
		public InlineQueryResultsButton() {}

		/**
		 * Represents a button to be shown above inline query results.
		 *
		 * @param text The text of the button.
		 * @param type Type of the button.
		**/
		public InlineQueryResultsButton(String text, InlineQueryResultsButtonType type) {
			this.text = text;
			this.type = type;
		}

		/**
		 * Represents a button to be shown above inline query results.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InlineQueryResultsButton(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] textTmp = new byte[input.readInt()];
				input.readFully(textTmp);
				this.text = new String(textTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InlineQueryResultsButtonTypeStartBot.CONSTRUCTOR: this.type = new InlineQueryResultsButtonTypeStartBot(input); break;
					case InlineQueryResultsButtonTypeWebApp.CONSTRUCTOR: this.type = new InlineQueryResultsButtonTypeWebApp(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InlineQueryResultsButton.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InlineQueryResultsButton.CONSTRUCTOR);
			if (this.text == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] textTmp = this.text.getBytes(StandardCharsets.UTF_8);
				output.writeInt(textTmp.length);
				output.write(textTmp);
			}
			if (this.type == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.type.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InlineQueryResultsButton inlineQueryResultsButton = (InlineQueryResultsButton) o;
			if (this.text != inlineQueryResultsButton.text) {
				return false;
			}
			if (!Objects.equals(this.type, inlineQueryResultsButton.type)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.text == null ? 0 : this.text.hashCode();
			result = result * 31 + (this.type == null ? 0 : this.type.hashCode());
			return result;
		}
	}

	/**
	 * Describes the button that opens a private chat with the bot and sends
	 * a start message to the bot with the given parameter.
	**/
	public static final class InlineQueryResultsButtonTypeStartBot extends InlineQueryResultsButtonType {


		/**
		 * The parameter for the bot start message.
		**/
		public String parameter;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -23400235;

		/**
		 * Describes the button that opens a private chat with the bot and sends a start message to the bot with the given parameter.
		**/
		public InlineQueryResultsButtonTypeStartBot() {}

		/**
		 * Describes the button that opens a private chat with the bot and sends a start message to the bot with the given parameter.
		 *
		 * @param parameter The parameter for the bot start message.
		**/
		public InlineQueryResultsButtonTypeStartBot(String parameter) {
			this.parameter = parameter;
		}

		/**
		 * Describes the button that opens a private chat with the bot and sends a start message to the bot with the given parameter.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InlineQueryResultsButtonTypeStartBot(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] parameterTmp = new byte[input.readInt()];
				input.readFully(parameterTmp);
				this.parameter = new String(parameterTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InlineQueryResultsButtonTypeStartBot.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InlineQueryResultsButtonTypeStartBot.CONSTRUCTOR);
			if (this.parameter == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] parameterTmp = this.parameter.getBytes(StandardCharsets.UTF_8);
				output.writeInt(parameterTmp.length);
				output.write(parameterTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InlineQueryResultsButtonTypeStartBot inlineQueryResultsButtonTypeStartBot = (InlineQueryResultsButtonTypeStartBot) o;
			if (this.parameter != inlineQueryResultsButtonTypeStartBot.parameter) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.parameter == null ? 0 : this.parameter.hashCode();
		}
	}

	/**
	 * Describes the button that opens a Web App by calling getWebAppUrl.
	**/
	public static final class InlineQueryResultsButtonTypeWebApp extends InlineQueryResultsButtonType {


		/**
		 * An HTTP URL to pass to getWebAppUrl.
		**/
		public String url;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1197382814;

		/**
		 * Describes the button that opens a Web App by calling getWebAppUrl.
		**/
		public InlineQueryResultsButtonTypeWebApp() {}

		/**
		 * Describes the button that opens a Web App by calling getWebAppUrl.
		 *
		 * @param url An HTTP URL to pass to getWebAppUrl.
		**/
		public InlineQueryResultsButtonTypeWebApp(String url) {
			this.url = url;
		}

		/**
		 * Describes the button that opens a Web App by calling getWebAppUrl.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InlineQueryResultsButtonTypeWebApp(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] urlTmp = new byte[input.readInt()];
				input.readFully(urlTmp);
				this.url = new String(urlTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InlineQueryResultsButtonTypeWebApp.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InlineQueryResultsButtonTypeWebApp.CONSTRUCTOR);
			if (this.url == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] urlTmp = this.url.getBytes(StandardCharsets.UTF_8);
				output.writeInt(urlTmp.length);
				output.write(urlTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InlineQueryResultsButtonTypeWebApp inlineQueryResultsButtonTypeWebApp = (InlineQueryResultsButtonTypeWebApp) o;
			if (this.url != inlineQueryResultsButtonTypeWebApp.url) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.url == null ? 0 : this.url.hashCode();
		}
	}

	/**
	 * A background from a local file.
	**/
	public static final class InputBackgroundLocal extends InputBackground {


		/**
		 * Background file to use. Only inputFileLocal and inputFileGenerated are supported. The file must be in JPEG format for wallpapers and in PNG format for patterns.
		**/
		public InputFile background;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1747094364;

		/**
		 * A background from a local file.
		**/
		public InputBackgroundLocal() {}

		/**
		 * A background from a local file.
		 *
		 * @param background Background file to use. Only inputFileLocal and inputFileGenerated are supported. The file must be in JPEG format for wallpapers and in PNG format for patterns.
		**/
		public InputBackgroundLocal(InputFile background) {
			this.background = background;
		}

		/**
		 * A background from a local file.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputBackgroundLocal(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputFileId.CONSTRUCTOR: this.background = new InputFileId(input); break;
					case InputFileRemote.CONSTRUCTOR: this.background = new InputFileRemote(input); break;
					case InputFileLocal.CONSTRUCTOR: this.background = new InputFileLocal(input); break;
					case InputFileGenerated.CONSTRUCTOR: this.background = new InputFileGenerated(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputBackgroundLocal.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputBackgroundLocal.CONSTRUCTOR);
			if (this.background == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.background.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputBackgroundLocal inputBackgroundLocal = (InputBackgroundLocal) o;
			if (!Objects.equals(this.background, inputBackgroundLocal.background)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.background == null ? 0 : this.background.hashCode();
		}
	}

	/**
	 * A background from the server.
	**/
	public static final class InputBackgroundRemote extends InputBackground {


		/**
		 * The background identifier.
		**/
		public long backgroundId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -274976231;

		/**
		 * A background from the server.
		**/
		public InputBackgroundRemote() {}

		/**
		 * A background from the server.
		 *
		 * @param backgroundId The background identifier.
		**/
		public InputBackgroundRemote(long backgroundId) {
			this.backgroundId = backgroundId;
		}

		/**
		 * A background from the server.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputBackgroundRemote(DataInput input) throws IOException {
			this.backgroundId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputBackgroundRemote.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputBackgroundRemote.CONSTRUCTOR);
			output.writeLong(this.backgroundId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputBackgroundRemote inputBackgroundRemote = (InputBackgroundRemote) o;
			if (this.backgroundId != inputBackgroundRemote.backgroundId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.backgroundId);
		}
	}

	/**
	 * A background previously set in the chat; for chat backgrounds only.
	**/
	public static final class InputBackgroundPrevious extends InputBackground {


		/**
		 * Identifier of the message with the background.
		**/
		public long messageId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -351905954;

		/**
		 * A background previously set in the chat; for chat backgrounds only.
		**/
		public InputBackgroundPrevious() {}

		/**
		 * A background previously set in the chat; for chat backgrounds only.
		 *
		 * @param messageId Identifier of the message with the background.
		**/
		public InputBackgroundPrevious(long messageId) {
			this.messageId = messageId;
		}

		/**
		 * A background previously set in the chat; for chat backgrounds only.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputBackgroundPrevious(DataInput input) throws IOException {
			this.messageId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputBackgroundPrevious.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputBackgroundPrevious.CONSTRUCTOR);
			output.writeLong(this.messageId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputBackgroundPrevious inputBackgroundPrevious = (InputBackgroundPrevious) o;
			if (this.messageId != inputBackgroundPrevious.messageId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.messageId);
		}
	}

	/**
	 * A previously used profile photo of the current user.
	**/
	public static final class InputChatPhotoPrevious extends InputChatPhoto {


		/**
		 * Identifier of the current user&#039;s profile photo to reuse.
		**/
		public long chatPhotoId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 23128529;

		/**
		 * A previously used profile photo of the current user.
		**/
		public InputChatPhotoPrevious() {}

		/**
		 * A previously used profile photo of the current user.
		 *
		 * @param chatPhotoId Identifier of the current user&#039;s profile photo to reuse.
		**/
		public InputChatPhotoPrevious(long chatPhotoId) {
			this.chatPhotoId = chatPhotoId;
		}

		/**
		 * A previously used profile photo of the current user.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputChatPhotoPrevious(DataInput input) throws IOException {
			this.chatPhotoId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputChatPhotoPrevious.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputChatPhotoPrevious.CONSTRUCTOR);
			output.writeLong(this.chatPhotoId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputChatPhotoPrevious inputChatPhotoPrevious = (InputChatPhotoPrevious) o;
			if (this.chatPhotoId != inputChatPhotoPrevious.chatPhotoId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.chatPhotoId);
		}
	}

	/**
	 * A static photo in JPEG format.
	**/
	public static final class InputChatPhotoStatic extends InputChatPhoto {


		/**
		 * Photo to be set as profile photo. Only inputFileLocal and inputFileGenerated are allowed.
		**/
		public InputFile photo;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1979179699;

		/**
		 * A static photo in JPEG format.
		**/
		public InputChatPhotoStatic() {}

		/**
		 * A static photo in JPEG format.
		 *
		 * @param photo Photo to be set as profile photo. Only inputFileLocal and inputFileGenerated are allowed.
		**/
		public InputChatPhotoStatic(InputFile photo) {
			this.photo = photo;
		}

		/**
		 * A static photo in JPEG format.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputChatPhotoStatic(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputFileId.CONSTRUCTOR: this.photo = new InputFileId(input); break;
					case InputFileRemote.CONSTRUCTOR: this.photo = new InputFileRemote(input); break;
					case InputFileLocal.CONSTRUCTOR: this.photo = new InputFileLocal(input); break;
					case InputFileGenerated.CONSTRUCTOR: this.photo = new InputFileGenerated(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputChatPhotoStatic.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputChatPhotoStatic.CONSTRUCTOR);
			if (this.photo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.photo.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputChatPhotoStatic inputChatPhotoStatic = (InputChatPhotoStatic) o;
			if (!Objects.equals(this.photo, inputChatPhotoStatic.photo)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.photo == null ? 0 : this.photo.hashCode();
		}
	}

	/**
	 * An animation in MPEG4 format; must be square, at most 10 seconds
	 * long, have width between 160 and 1280 and be at most 2MB in size.
	**/
	public static final class InputChatPhotoAnimation extends InputChatPhoto {


		/**
		 * Animation to be set as profile photo. Only inputFileLocal and inputFileGenerated are allowed.
		**/
		public InputFile animation;

		/**
		 * Timestamp of the frame, which will be used as static chat photo.
		**/
		public double mainFrameTimestamp;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 90846242;

		/**
		 * An animation in MPEG4 format; must be square, at most 10 seconds long, have width between 160 and 1280 and be at most 2MB in size.
		**/
		public InputChatPhotoAnimation() {}

		/**
		 * An animation in MPEG4 format; must be square, at most 10 seconds long, have width between 160 and 1280 and be at most 2MB in size.
		 *
		 * @param animation Animation to be set as profile photo. Only inputFileLocal and inputFileGenerated are allowed.
		 * @param mainFrameTimestamp Timestamp of the frame, which will be used as static chat photo.
		**/
		public InputChatPhotoAnimation(InputFile animation, double mainFrameTimestamp) {
			this.animation = animation;
			this.mainFrameTimestamp = mainFrameTimestamp;
		}

		/**
		 * An animation in MPEG4 format; must be square, at most 10 seconds long, have width between 160 and 1280 and be at most 2MB in size.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputChatPhotoAnimation(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputFileId.CONSTRUCTOR: this.animation = new InputFileId(input); break;
					case InputFileRemote.CONSTRUCTOR: this.animation = new InputFileRemote(input); break;
					case InputFileLocal.CONSTRUCTOR: this.animation = new InputFileLocal(input); break;
					case InputFileGenerated.CONSTRUCTOR: this.animation = new InputFileGenerated(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.mainFrameTimestamp = input.readDouble();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputChatPhotoAnimation.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputChatPhotoAnimation.CONSTRUCTOR);
			if (this.animation == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.animation.serialize(output);
			}
			output.writeDouble(this.mainFrameTimestamp);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputChatPhotoAnimation inputChatPhotoAnimation = (InputChatPhotoAnimation) o;
			if (!Objects.equals(this.animation, inputChatPhotoAnimation.animation)) {
				return false;
			}
			if (this.mainFrameTimestamp != inputChatPhotoAnimation.mainFrameTimestamp) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Double.hashCode(this.mainFrameTimestamp);
			result = result * 31 + (this.animation == null ? 0 : this.animation.hashCode());
			return result;
		}
	}

	/**
	 * A sticker on a custom background.
	**/
	public static final class InputChatPhotoSticker extends InputChatPhoto {


		/**
		 * Information about the sticker.
		**/
		public ChatPhotoSticker sticker;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1315861341;

		/**
		 * A sticker on a custom background.
		**/
		public InputChatPhotoSticker() {}

		/**
		 * A sticker on a custom background.
		 *
		 * @param sticker Information about the sticker.
		**/
		public InputChatPhotoSticker(ChatPhotoSticker sticker) {
			this.sticker = sticker;
		}

		/**
		 * A sticker on a custom background.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputChatPhotoSticker(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (ChatPhotoSticker.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.sticker = new ChatPhotoSticker(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputChatPhotoSticker.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputChatPhotoSticker.CONSTRUCTOR);
			if (this.sticker == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.sticker.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputChatPhotoSticker inputChatPhotoSticker = (InputChatPhotoSticker) o;
			if (!Objects.equals(this.sticker, inputChatPhotoSticker.sticker)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.sticker == null ? 0 : this.sticker.hashCode();
		}
	}

	/**
	 * Applies if a user chooses some previously saved payment credentials.
	 * To use their previously saved credentials, the user must have a valid
	 * temporary password.
	**/
	public static final class InputCredentialsSaved extends InputCredentials {


		/**
		 * Identifier of the saved credentials.
		**/
		public String savedCredentialsId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2034385364;

		/**
		 * Applies if a user chooses some previously saved payment credentials. To use their previously saved credentials, the user must have a valid temporary password.
		**/
		public InputCredentialsSaved() {}

		/**
		 * Applies if a user chooses some previously saved payment credentials. To use their previously saved credentials, the user must have a valid temporary password.
		 *
		 * @param savedCredentialsId Identifier of the saved credentials.
		**/
		public InputCredentialsSaved(String savedCredentialsId) {
			this.savedCredentialsId = savedCredentialsId;
		}

		/**
		 * Applies if a user chooses some previously saved payment credentials. To use their previously saved credentials, the user must have a valid temporary password.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputCredentialsSaved(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] savedCredentialsIdTmp = new byte[input.readInt()];
				input.readFully(savedCredentialsIdTmp);
				this.savedCredentialsId = new String(savedCredentialsIdTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputCredentialsSaved.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputCredentialsSaved.CONSTRUCTOR);
			if (this.savedCredentialsId == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] savedCredentialsIdTmp = this.savedCredentialsId.getBytes(StandardCharsets.UTF_8);
				output.writeInt(savedCredentialsIdTmp.length);
				output.write(savedCredentialsIdTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputCredentialsSaved inputCredentialsSaved = (InputCredentialsSaved) o;
			if (this.savedCredentialsId != inputCredentialsSaved.savedCredentialsId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.savedCredentialsId == null ? 0 : this.savedCredentialsId.hashCode();
		}
	}

	/**
	 * Applies if a user enters new credentials on a payment provider
	 * website.
	**/
	public static final class InputCredentialsNew extends InputCredentials {


		/**
		 * JSON-encoded data with the credential identifier from the payment provider.
		**/
		public String data;

		/**
		 * True, if the credential identifier can be saved on the server side.
		**/
		public boolean allowSave;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -829689558;

		/**
		 * Applies if a user enters new credentials on a payment provider website.
		**/
		public InputCredentialsNew() {}

		/**
		 * Applies if a user enters new credentials on a payment provider website.
		 *
		 * @param data JSON-encoded data with the credential identifier from the payment provider.
		 * @param allowSave True, if the credential identifier can be saved on the server side.
		**/
		public InputCredentialsNew(String data, boolean allowSave) {
			this.data = data;
			this.allowSave = allowSave;
		}

		/**
		 * Applies if a user enters new credentials on a payment provider website.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputCredentialsNew(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] dataTmp = new byte[input.readInt()];
				input.readFully(dataTmp);
				this.data = new String(dataTmp, StandardCharsets.UTF_8);
			}
			this.allowSave = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputCredentialsNew.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputCredentialsNew.CONSTRUCTOR);
			if (this.data == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] dataTmp = this.data.getBytes(StandardCharsets.UTF_8);
				output.writeInt(dataTmp.length);
				output.write(dataTmp);
			}
			output.writeBoolean(this.allowSave);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputCredentialsNew inputCredentialsNew = (InputCredentialsNew) o;
			if (this.data != inputCredentialsNew.data) {
				return false;
			}
			if (this.allowSave != inputCredentialsNew.allowSave) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.allowSave);
			result = result * 31 + (this.data == null ? 0 : this.data.hashCode());
			return result;
		}
	}

	/**
	 * Applies if a user enters new credentials using Apple Pay.
	**/
	public static final class InputCredentialsApplePay extends InputCredentials {


		/**
		 * JSON-encoded data with the credential identifier.
		**/
		public String data;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1246570799;

		/**
		 * Applies if a user enters new credentials using Apple Pay.
		**/
		public InputCredentialsApplePay() {}

		/**
		 * Applies if a user enters new credentials using Apple Pay.
		 *
		 * @param data JSON-encoded data with the credential identifier.
		**/
		public InputCredentialsApplePay(String data) {
			this.data = data;
		}

		/**
		 * Applies if a user enters new credentials using Apple Pay.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputCredentialsApplePay(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] dataTmp = new byte[input.readInt()];
				input.readFully(dataTmp);
				this.data = new String(dataTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputCredentialsApplePay.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputCredentialsApplePay.CONSTRUCTOR);
			if (this.data == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] dataTmp = this.data.getBytes(StandardCharsets.UTF_8);
				output.writeInt(dataTmp.length);
				output.write(dataTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputCredentialsApplePay inputCredentialsApplePay = (InputCredentialsApplePay) o;
			if (this.data != inputCredentialsApplePay.data) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.data == null ? 0 : this.data.hashCode();
		}
	}

	/**
	 * Applies if a user enters new credentials using Google Pay.
	**/
	public static final class InputCredentialsGooglePay extends InputCredentials {


		/**
		 * JSON-encoded data with the credential identifier.
		**/
		public String data;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 844384100;

		/**
		 * Applies if a user enters new credentials using Google Pay.
		**/
		public InputCredentialsGooglePay() {}

		/**
		 * Applies if a user enters new credentials using Google Pay.
		 *
		 * @param data JSON-encoded data with the credential identifier.
		**/
		public InputCredentialsGooglePay(String data) {
			this.data = data;
		}

		/**
		 * Applies if a user enters new credentials using Google Pay.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputCredentialsGooglePay(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] dataTmp = new byte[input.readInt()];
				input.readFully(dataTmp);
				this.data = new String(dataTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputCredentialsGooglePay.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputCredentialsGooglePay.CONSTRUCTOR);
			if (this.data == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] dataTmp = this.data.getBytes(StandardCharsets.UTF_8);
				output.writeInt(dataTmp.length);
				output.write(dataTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputCredentialsGooglePay inputCredentialsGooglePay = (InputCredentialsGooglePay) o;
			if (this.data != inputCredentialsGooglePay.data) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.data == null ? 0 : this.data.hashCode();
		}
	}

	/**
	 * A file defined by its unique ID.
	**/
	public static final class InputFileId extends InputFile {


		/**
		 * Unique file identifier.
		**/
		public int id;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1788906253;

		/**
		 * A file defined by its unique ID.
		**/
		public InputFileId() {}

		/**
		 * A file defined by its unique ID.
		 *
		 * @param id Unique file identifier.
		**/
		public InputFileId(int id) {
			this.id = id;
		}

		/**
		 * A file defined by its unique ID.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputFileId(DataInput input) throws IOException {
			this.id = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputFileId.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputFileId.CONSTRUCTOR);
			output.writeInt(this.id);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputFileId inputFileId = (InputFileId) o;
			if (this.id != inputFileId.id) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.id);
		}
	}

	/**
	 * A file defined by its remote ID. The remote ID is guaranteed to be
	 * usable only if the corresponding file is still accessible to the user
	 * and known to TDLib. For example, if the file is from a message, then
	 * the message must be not deleted and accessible to the user. If the
	 * file database is disabled, then the corresponding object with the
	 * file must be preloaded by the application.
	**/
	public static final class InputFileRemote extends InputFile {


		/**
		 * Remote file identifier.
		**/
		public String id;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -107574466;

		/**
		 * A file defined by its remote ID. The remote ID is guaranteed to be usable only if the corresponding file is still accessible to the user and known to TDLib. For example, if the file is from a message, then the message must be not deleted and accessible to the user. If the file database is disabled, then the corresponding object with the file must be preloaded by the application.
		**/
		public InputFileRemote() {}

		/**
		 * A file defined by its remote ID. The remote ID is guaranteed to be usable only if the corresponding file is still accessible to the user and known to TDLib. For example, if the file is from a message, then the message must be not deleted and accessible to the user. If the file database is disabled, then the corresponding object with the file must be preloaded by the application.
		 *
		 * @param id Remote file identifier.
		**/
		public InputFileRemote(String id) {
			this.id = id;
		}

		/**
		 * A file defined by its remote ID. The remote ID is guaranteed to be usable only if the corresponding file is still accessible to the user and known to TDLib. For example, if the file is from a message, then the message must be not deleted and accessible to the user. If the file database is disabled, then the corresponding object with the file must be preloaded by the application.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputFileRemote(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] idTmp = new byte[input.readInt()];
				input.readFully(idTmp);
				this.id = new String(idTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputFileRemote.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputFileRemote.CONSTRUCTOR);
			if (this.id == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] idTmp = this.id.getBytes(StandardCharsets.UTF_8);
				output.writeInt(idTmp.length);
				output.write(idTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputFileRemote inputFileRemote = (InputFileRemote) o;
			if (this.id != inputFileRemote.id) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.id == null ? 0 : this.id.hashCode();
		}
	}

	/**
	 * A file defined by a local path.
	**/
	public static final class InputFileLocal extends InputFile {


		/**
		 * Local path to the file.
		**/
		public String path;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2056030919;

		/**
		 * A file defined by a local path.
		**/
		public InputFileLocal() {}

		/**
		 * A file defined by a local path.
		 *
		 * @param path Local path to the file.
		**/
		public InputFileLocal(String path) {
			this.path = path;
		}

		/**
		 * A file defined by a local path.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputFileLocal(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] pathTmp = new byte[input.readInt()];
				input.readFully(pathTmp);
				this.path = new String(pathTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputFileLocal.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputFileLocal.CONSTRUCTOR);
			if (this.path == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] pathTmp = this.path.getBytes(StandardCharsets.UTF_8);
				output.writeInt(pathTmp.length);
				output.write(pathTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputFileLocal inputFileLocal = (InputFileLocal) o;
			if (this.path != inputFileLocal.path) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.path == null ? 0 : this.path.hashCode();
		}
	}

	/**
	 * A file generated by the application.
	**/
	public static final class InputFileGenerated extends InputFile {


		/**
		 * Local path to a file from which the file is generated; may be empty if there is no such file.
		**/
		public String originalPath;

		/**
		 * String specifying the conversion applied to the original file; must be persistent across application restarts. Conversions beginning with &#039;#&#039; are reserved for internal TDLib usage.
		**/
		public String conversion;

		/**
		 * Expected size of the generated file, in bytes; 0 if unknown.
		**/
		public long expectedSize;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1333385216;

		/**
		 * A file generated by the application.
		**/
		public InputFileGenerated() {}

		/**
		 * A file generated by the application.
		 *
		 * @param originalPath Local path to a file from which the file is generated; may be empty if there is no such file.
		 * @param conversion String specifying the conversion applied to the original file; must be persistent across application restarts. Conversions beginning with &#039;#&#039; are reserved for internal TDLib usage.
		 * @param expectedSize Expected size of the generated file, in bytes; 0 if unknown.
		**/
		public InputFileGenerated(String originalPath, String conversion, long expectedSize) {
			this.originalPath = originalPath;
			this.conversion = conversion;
			this.expectedSize = expectedSize;
		}

		/**
		 * A file generated by the application.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputFileGenerated(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] originalPathTmp = new byte[input.readInt()];
				input.readFully(originalPathTmp);
				this.originalPath = new String(originalPathTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] conversionTmp = new byte[input.readInt()];
				input.readFully(conversionTmp);
				this.conversion = new String(conversionTmp, StandardCharsets.UTF_8);
			}
			this.expectedSize = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputFileGenerated.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputFileGenerated.CONSTRUCTOR);
			if (this.originalPath == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] originalPathTmp = this.originalPath.getBytes(StandardCharsets.UTF_8);
				output.writeInt(originalPathTmp.length);
				output.write(originalPathTmp);
			}
			if (this.conversion == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] conversionTmp = this.conversion.getBytes(StandardCharsets.UTF_8);
				output.writeInt(conversionTmp.length);
				output.write(conversionTmp);
			}
			output.writeLong(this.expectedSize);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputFileGenerated inputFileGenerated = (InputFileGenerated) o;
			if (this.originalPath != inputFileGenerated.originalPath) {
				return false;
			}
			if (this.conversion != inputFileGenerated.conversion) {
				return false;
			}
			if (this.expectedSize != inputFileGenerated.expectedSize) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.expectedSize);
			result = result * 31 + (this.originalPath == null ? 0 : this.originalPath.hashCode());
			result = result * 31 + (this.conversion == null ? 0 : this.conversion.hashCode());
			return result;
		}
	}

	/**
	 * An identity document to be saved to Telegram Passport.
	**/
	public static final class InputIdentityDocument extends Object {


		/**
		 * Document number; 1-24 characters.
		**/
		public String number;

		/**
		 * Document expiry date; pass null if not applicable.
		**/
		public Date expiryDate;

		/**
		 * Front side of the document.
		**/
		public InputFile frontSide;

		/**
		 * Reverse side of the document; only for driver license and identity card; pass null otherwise.
		**/
		public InputFile reverseSide;

		/**
		 * Selfie with the document; pass null if unavailable.
		**/
		public InputFile selfie;

		/**
		 * List of files containing a certified English translation of the document.
		**/
		public InputFile[] translation;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -381776063;

		/**
		 * An identity document to be saved to Telegram Passport.
		**/
		public InputIdentityDocument() {}

		/**
		 * An identity document to be saved to Telegram Passport.
		 *
		 * @param number Document number; 1-24 characters.
		 * @param expiryDate Document expiry date; pass null if not applicable.
		 * @param frontSide Front side of the document.
		 * @param reverseSide Reverse side of the document; only for driver license and identity card; pass null otherwise.
		 * @param selfie Selfie with the document; pass null if unavailable.
		 * @param translation List of files containing a certified English translation of the document.
		**/
		public InputIdentityDocument(String number,
				Date expiryDate,
				InputFile frontSide,
				InputFile reverseSide,
				InputFile selfie,
				InputFile[] translation) {
			this.number = number;
			this.expiryDate = expiryDate;
			this.frontSide = frontSide;
			this.reverseSide = reverseSide;
			this.selfie = selfie;
			this.translation = translation;
		}

		/**
		 * An identity document to be saved to Telegram Passport.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputIdentityDocument(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] numberTmp = new byte[input.readInt()];
				input.readFully(numberTmp);
				this.number = new String(numberTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (Date.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.expiryDate = new Date(input);
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputFileId.CONSTRUCTOR: this.frontSide = new InputFileId(input); break;
					case InputFileRemote.CONSTRUCTOR: this.frontSide = new InputFileRemote(input); break;
					case InputFileLocal.CONSTRUCTOR: this.frontSide = new InputFileLocal(input); break;
					case InputFileGenerated.CONSTRUCTOR: this.frontSide = new InputFileGenerated(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputFileId.CONSTRUCTOR: this.reverseSide = new InputFileId(input); break;
					case InputFileRemote.CONSTRUCTOR: this.reverseSide = new InputFileRemote(input); break;
					case InputFileLocal.CONSTRUCTOR: this.reverseSide = new InputFileLocal(input); break;
					case InputFileGenerated.CONSTRUCTOR: this.reverseSide = new InputFileGenerated(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputFileId.CONSTRUCTOR: this.selfie = new InputFileId(input); break;
					case InputFileRemote.CONSTRUCTOR: this.selfie = new InputFileRemote(input); break;
					case InputFileLocal.CONSTRUCTOR: this.selfie = new InputFileLocal(input); break;
					case InputFileGenerated.CONSTRUCTOR: this.selfie = new InputFileGenerated(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				this.translation = new InputFile[input.readInt()];
				for (int i = 0; i < this.translation.length; i++) {
					switch(input.readInt()) {
						case InputFileId.CONSTRUCTOR: this.translation[i] = new InputFileId(input); break;
						case InputFileRemote.CONSTRUCTOR: this.translation[i] = new InputFileRemote(input); break;
						case InputFileLocal.CONSTRUCTOR: this.translation[i] = new InputFileLocal(input); break;
						case InputFileGenerated.CONSTRUCTOR: this.translation[i] = new InputFileGenerated(input); break;
						default: {
							throw new UnsupportedOperationException();
						}
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputIdentityDocument.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputIdentityDocument.CONSTRUCTOR);
			if (this.number == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] numberTmp = this.number.getBytes(StandardCharsets.UTF_8);
				output.writeInt(numberTmp.length);
				output.write(numberTmp);
			}
			if (this.expiryDate == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.expiryDate.serialize(output);
			}
			if (this.frontSide == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.frontSide.serialize(output);
			}
			if (this.reverseSide == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.reverseSide.serialize(output);
			}
			if (this.selfie == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.selfie.serialize(output);
			}
			if (this.translation == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.translation.length);
				for (int i = 0; i < this.translation.length; i++) {
					this.translation[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputIdentityDocument inputIdentityDocument = (InputIdentityDocument) o;
			if (this.number != inputIdentityDocument.number) {
				return false;
			}
			if (!Objects.equals(this.expiryDate, inputIdentityDocument.expiryDate)) {
				return false;
			}
			if (!Objects.equals(this.frontSide, inputIdentityDocument.frontSide)) {
				return false;
			}
			if (!Objects.equals(this.reverseSide, inputIdentityDocument.reverseSide)) {
				return false;
			}
			if (!Objects.equals(this.selfie, inputIdentityDocument.selfie)) {
				return false;
			}
			if (!Arrays.equals(this.translation, inputIdentityDocument.translation)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.number == null ? 0 : this.number.hashCode();
			result = result * 31 + (this.expiryDate == null ? 0 : this.expiryDate.hashCode());
			result = result * 31 + (this.frontSide == null ? 0 : this.frontSide.hashCode());
			result = result * 31 + (this.reverseSide == null ? 0 : this.reverseSide.hashCode());
			result = result * 31 + (this.selfie == null ? 0 : this.selfie.hashCode());
			result = result * 31 + (Arrays.hashCode(this.translation));
			return result;
		}
	}

	/**
	 * Represents a link to an animated GIF or an animated (i.e., without
	 * sound) H.264/MPEG-4 AVC video.
	**/
	public static final class InputInlineQueryResultAnimation extends InputInlineQueryResult {


		/**
		 * Unique identifier of the query result.
		**/
		public String id;

		/**
		 * Title of the query result.
		**/
		public String title;

		/**
		 * URL of the result thumbnail (JPEG, GIF, or MPEG4), if it exists.
		**/
		public String thumbnailUrl;

		/**
		 * MIME type of the video thumbnail. If non-empty, must be one of &quot;image/jpeg&quot;, &quot;image/gif&quot; and &quot;video/mp4&quot;.
		**/
		public String thumbnailMimeType;

		/**
		 * The URL of the video file (file size must not exceed 1MB).
		**/
		public String videoUrl;

		/**
		 * MIME type of the video file. Must be one of &quot;image/gif&quot; and &quot;video/mp4&quot;.
		**/
		public String videoMimeType;

		/**
		 * Duration of the video, in seconds.
		**/
		public int videoDuration;

		/**
		 * Width of the video.
		**/
		public int videoWidth;

		/**
		 * Height of the video.
		**/
		public int videoHeight;

		/**
		 * The message reply markup; pass null if none. Must be of type replyMarkupInlineKeyboard or null.
		**/
		public ReplyMarkup replyMarkup;

		/**
		 * The content of the message to be sent. Must be one of the following types: inputMessageText, inputMessageAnimation, inputMessageInvoice, inputMessageLocation, inputMessageVenue or inputMessageContact.
		**/
		public InputMessageContent inputMessageContent;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1489808874;

		/**
		 * Represents a link to an animated GIF or an animated (i.e., without sound) H.264/MPEG-4 AVC video.
		**/
		public InputInlineQueryResultAnimation() {}

		/**
		 * Represents a link to an animated GIF or an animated (i.e., without sound) H.264/MPEG-4 AVC video.
		 *
		 * @param id Unique identifier of the query result.
		 * @param title Title of the query result.
		 * @param thumbnailUrl URL of the result thumbnail (JPEG, GIF, or MPEG4), if it exists.
		 * @param thumbnailMimeType MIME type of the video thumbnail. If non-empty, must be one of &quot;image/jpeg&quot;, &quot;image/gif&quot; and &quot;video/mp4&quot;.
		 * @param videoUrl The URL of the video file (file size must not exceed 1MB).
		 * @param videoMimeType MIME type of the video file. Must be one of &quot;image/gif&quot; and &quot;video/mp4&quot;.
		 * @param videoDuration Duration of the video, in seconds.
		 * @param videoWidth Width of the video.
		 * @param videoHeight Height of the video.
		 * @param replyMarkup The message reply markup; pass null if none. Must be of type replyMarkupInlineKeyboard or null.
		 * @param inputMessageContent The content of the message to be sent. Must be one of the following types: inputMessageText, inputMessageAnimation, inputMessageInvoice, inputMessageLocation, inputMessageVenue or inputMessageContact.
		**/
		public InputInlineQueryResultAnimation(String id,
				String title,
				String thumbnailUrl,
				String thumbnailMimeType,
				String videoUrl,
				String videoMimeType,
				int videoDuration,
				int videoWidth,
				int videoHeight,
				ReplyMarkup replyMarkup,
				InputMessageContent inputMessageContent) {
			this.id = id;
			this.title = title;
			this.thumbnailUrl = thumbnailUrl;
			this.thumbnailMimeType = thumbnailMimeType;
			this.videoUrl = videoUrl;
			this.videoMimeType = videoMimeType;
			this.videoDuration = videoDuration;
			this.videoWidth = videoWidth;
			this.videoHeight = videoHeight;
			this.replyMarkup = replyMarkup;
			this.inputMessageContent = inputMessageContent;
		}

		/**
		 * Represents a link to an animated GIF or an animated (i.e., without sound) H.264/MPEG-4 AVC video.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputInlineQueryResultAnimation(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] idTmp = new byte[input.readInt()];
				input.readFully(idTmp);
				this.id = new String(idTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] thumbnailUrlTmp = new byte[input.readInt()];
				input.readFully(thumbnailUrlTmp);
				this.thumbnailUrl = new String(thumbnailUrlTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] thumbnailMimeTypeTmp = new byte[input.readInt()];
				input.readFully(thumbnailMimeTypeTmp);
				this.thumbnailMimeType = new String(thumbnailMimeTypeTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] videoUrlTmp = new byte[input.readInt()];
				input.readFully(videoUrlTmp);
				this.videoUrl = new String(videoUrlTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] videoMimeTypeTmp = new byte[input.readInt()];
				input.readFully(videoMimeTypeTmp);
				this.videoMimeType = new String(videoMimeTypeTmp, StandardCharsets.UTF_8);
			}
			this.videoDuration = input.readInt();
			this.videoWidth = input.readInt();
			this.videoHeight = input.readInt();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ReplyMarkupRemoveKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupRemoveKeyboard(input); break;
					case ReplyMarkupForceReply.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupForceReply(input); break;
					case ReplyMarkupShowKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupShowKeyboard(input); break;
					case ReplyMarkupInlineKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupInlineKeyboard(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputMessageText.CONSTRUCTOR: this.inputMessageContent = new InputMessageText(input); break;
					case InputMessageAnimation.CONSTRUCTOR: this.inputMessageContent = new InputMessageAnimation(input); break;
					case InputMessageAudio.CONSTRUCTOR: this.inputMessageContent = new InputMessageAudio(input); break;
					case InputMessageDocument.CONSTRUCTOR: this.inputMessageContent = new InputMessageDocument(input); break;
					case InputMessagePhoto.CONSTRUCTOR: this.inputMessageContent = new InputMessagePhoto(input); break;
					case InputMessageSticker.CONSTRUCTOR: this.inputMessageContent = new InputMessageSticker(input); break;
					case InputMessageVideo.CONSTRUCTOR: this.inputMessageContent = new InputMessageVideo(input); break;
					case InputMessageVideoNote.CONSTRUCTOR: this.inputMessageContent = new InputMessageVideoNote(input); break;
					case InputMessageVoiceNote.CONSTRUCTOR: this.inputMessageContent = new InputMessageVoiceNote(input); break;
					case InputMessageLocation.CONSTRUCTOR: this.inputMessageContent = new InputMessageLocation(input); break;
					case InputMessageVenue.CONSTRUCTOR: this.inputMessageContent = new InputMessageVenue(input); break;
					case InputMessageContact.CONSTRUCTOR: this.inputMessageContent = new InputMessageContact(input); break;
					case InputMessageDice.CONSTRUCTOR: this.inputMessageContent = new InputMessageDice(input); break;
					case InputMessageGame.CONSTRUCTOR: this.inputMessageContent = new InputMessageGame(input); break;
					case InputMessageInvoice.CONSTRUCTOR: this.inputMessageContent = new InputMessageInvoice(input); break;
					case InputMessagePoll.CONSTRUCTOR: this.inputMessageContent = new InputMessagePoll(input); break;
					case InputMessageForwarded.CONSTRUCTOR: this.inputMessageContent = new InputMessageForwarded(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputInlineQueryResultAnimation.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputInlineQueryResultAnimation.CONSTRUCTOR);
			if (this.id == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] idTmp = this.id.getBytes(StandardCharsets.UTF_8);
				output.writeInt(idTmp.length);
				output.write(idTmp);
			}
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
			if (this.thumbnailUrl == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] thumbnailUrlTmp = this.thumbnailUrl.getBytes(StandardCharsets.UTF_8);
				output.writeInt(thumbnailUrlTmp.length);
				output.write(thumbnailUrlTmp);
			}
			if (this.thumbnailMimeType == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] thumbnailMimeTypeTmp = this.thumbnailMimeType.getBytes(StandardCharsets.UTF_8);
				output.writeInt(thumbnailMimeTypeTmp.length);
				output.write(thumbnailMimeTypeTmp);
			}
			if (this.videoUrl == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] videoUrlTmp = this.videoUrl.getBytes(StandardCharsets.UTF_8);
				output.writeInt(videoUrlTmp.length);
				output.write(videoUrlTmp);
			}
			if (this.videoMimeType == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] videoMimeTypeTmp = this.videoMimeType.getBytes(StandardCharsets.UTF_8);
				output.writeInt(videoMimeTypeTmp.length);
				output.write(videoMimeTypeTmp);
			}
			output.writeInt(this.videoDuration);
			output.writeInt(this.videoWidth);
			output.writeInt(this.videoHeight);
			if (this.replyMarkup == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.replyMarkup.serialize(output);
			}
			if (this.inputMessageContent == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.inputMessageContent.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputInlineQueryResultAnimation inputInlineQueryResultAnimation = (InputInlineQueryResultAnimation) o;
			if (this.id != inputInlineQueryResultAnimation.id) {
				return false;
			}
			if (this.title != inputInlineQueryResultAnimation.title) {
				return false;
			}
			if (this.thumbnailUrl != inputInlineQueryResultAnimation.thumbnailUrl) {
				return false;
			}
			if (this.thumbnailMimeType != inputInlineQueryResultAnimation.thumbnailMimeType) {
				return false;
			}
			if (this.videoUrl != inputInlineQueryResultAnimation.videoUrl) {
				return false;
			}
			if (this.videoMimeType != inputInlineQueryResultAnimation.videoMimeType) {
				return false;
			}
			if (this.videoDuration != inputInlineQueryResultAnimation.videoDuration) {
				return false;
			}
			if (this.videoWidth != inputInlineQueryResultAnimation.videoWidth) {
				return false;
			}
			if (this.videoHeight != inputInlineQueryResultAnimation.videoHeight) {
				return false;
			}
			if (!Objects.equals(this.replyMarkup, inputInlineQueryResultAnimation.replyMarkup)) {
				return false;
			}
			if (!Objects.equals(this.inputMessageContent, inputInlineQueryResultAnimation.inputMessageContent)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.videoDuration);
			result = result * 31 + (this.id == null ? 0 : this.id.hashCode());
			result = result * 31 + (this.title == null ? 0 : this.title.hashCode());
			result = result * 31 + (this.thumbnailUrl == null ? 0 : this.thumbnailUrl.hashCode());
			result = result * 31 + (this.thumbnailMimeType == null ? 0 : this.thumbnailMimeType.hashCode());
			result = result * 31 + (this.videoUrl == null ? 0 : this.videoUrl.hashCode());
			result = result * 31 + (this.videoMimeType == null ? 0 : this.videoMimeType.hashCode());
			result = result * 31 + (this.replyMarkup == null ? 0 : this.replyMarkup.hashCode());
			result = result * 31 + (this.inputMessageContent == null ? 0 : this.inputMessageContent.hashCode());
			return result;
		}
	}

	/**
	 * Represents a link to an article or web page.
	**/
	public static final class InputInlineQueryResultArticle extends InputInlineQueryResult {


		/**
		 * Unique identifier of the query result.
		**/
		public String id;

		/**
		 * URL of the result, if it exists.
		**/
		public String url;

		/**
		 * True, if the URL must be not shown.
		**/
		public boolean hideUrl;

		/**
		 * Title of the result.
		**/
		public String title;

		/**
		 * A short description of the result.
		**/
		public String description;

		/**
		 * URL of the result thumbnail, if it exists.
		**/
		public String thumbnailUrl;

		/**
		 * Thumbnail width, if known.
		**/
		public int thumbnailWidth;

		/**
		 * Thumbnail height, if known.
		**/
		public int thumbnailHeight;

		/**
		 * The message reply markup; pass null if none. Must be of type replyMarkupInlineKeyboard or null.
		**/
		public ReplyMarkup replyMarkup;

		/**
		 * The content of the message to be sent. Must be one of the following types: inputMessageText, inputMessageInvoice, inputMessageLocation, inputMessageVenue or inputMessageContact.
		**/
		public InputMessageContent inputMessageContent;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1973670156;

		/**
		 * Represents a link to an article or web page.
		**/
		public InputInlineQueryResultArticle() {}

		/**
		 * Represents a link to an article or web page.
		 *
		 * @param id Unique identifier of the query result.
		 * @param url URL of the result, if it exists.
		 * @param hideUrl True, if the URL must be not shown.
		 * @param title Title of the result.
		 * @param description A short description of the result.
		 * @param thumbnailUrl URL of the result thumbnail, if it exists.
		 * @param thumbnailWidth Thumbnail width, if known.
		 * @param thumbnailHeight Thumbnail height, if known.
		 * @param replyMarkup The message reply markup; pass null if none. Must be of type replyMarkupInlineKeyboard or null.
		 * @param inputMessageContent The content of the message to be sent. Must be one of the following types: inputMessageText, inputMessageInvoice, inputMessageLocation, inputMessageVenue or inputMessageContact.
		**/
		public InputInlineQueryResultArticle(String id,
				String url,
				boolean hideUrl,
				String title,
				String description,
				String thumbnailUrl,
				int thumbnailWidth,
				int thumbnailHeight,
				ReplyMarkup replyMarkup,
				InputMessageContent inputMessageContent) {
			this.id = id;
			this.url = url;
			this.hideUrl = hideUrl;
			this.title = title;
			this.description = description;
			this.thumbnailUrl = thumbnailUrl;
			this.thumbnailWidth = thumbnailWidth;
			this.thumbnailHeight = thumbnailHeight;
			this.replyMarkup = replyMarkup;
			this.inputMessageContent = inputMessageContent;
		}

		/**
		 * Represents a link to an article or web page.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputInlineQueryResultArticle(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] idTmp = new byte[input.readInt()];
				input.readFully(idTmp);
				this.id = new String(idTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] urlTmp = new byte[input.readInt()];
				input.readFully(urlTmp);
				this.url = new String(urlTmp, StandardCharsets.UTF_8);
			}
			this.hideUrl = input.readBoolean();
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] descriptionTmp = new byte[input.readInt()];
				input.readFully(descriptionTmp);
				this.description = new String(descriptionTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] thumbnailUrlTmp = new byte[input.readInt()];
				input.readFully(thumbnailUrlTmp);
				this.thumbnailUrl = new String(thumbnailUrlTmp, StandardCharsets.UTF_8);
			}
			this.thumbnailWidth = input.readInt();
			this.thumbnailHeight = input.readInt();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ReplyMarkupRemoveKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupRemoveKeyboard(input); break;
					case ReplyMarkupForceReply.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupForceReply(input); break;
					case ReplyMarkupShowKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupShowKeyboard(input); break;
					case ReplyMarkupInlineKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupInlineKeyboard(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputMessageText.CONSTRUCTOR: this.inputMessageContent = new InputMessageText(input); break;
					case InputMessageAnimation.CONSTRUCTOR: this.inputMessageContent = new InputMessageAnimation(input); break;
					case InputMessageAudio.CONSTRUCTOR: this.inputMessageContent = new InputMessageAudio(input); break;
					case InputMessageDocument.CONSTRUCTOR: this.inputMessageContent = new InputMessageDocument(input); break;
					case InputMessagePhoto.CONSTRUCTOR: this.inputMessageContent = new InputMessagePhoto(input); break;
					case InputMessageSticker.CONSTRUCTOR: this.inputMessageContent = new InputMessageSticker(input); break;
					case InputMessageVideo.CONSTRUCTOR: this.inputMessageContent = new InputMessageVideo(input); break;
					case InputMessageVideoNote.CONSTRUCTOR: this.inputMessageContent = new InputMessageVideoNote(input); break;
					case InputMessageVoiceNote.CONSTRUCTOR: this.inputMessageContent = new InputMessageVoiceNote(input); break;
					case InputMessageLocation.CONSTRUCTOR: this.inputMessageContent = new InputMessageLocation(input); break;
					case InputMessageVenue.CONSTRUCTOR: this.inputMessageContent = new InputMessageVenue(input); break;
					case InputMessageContact.CONSTRUCTOR: this.inputMessageContent = new InputMessageContact(input); break;
					case InputMessageDice.CONSTRUCTOR: this.inputMessageContent = new InputMessageDice(input); break;
					case InputMessageGame.CONSTRUCTOR: this.inputMessageContent = new InputMessageGame(input); break;
					case InputMessageInvoice.CONSTRUCTOR: this.inputMessageContent = new InputMessageInvoice(input); break;
					case InputMessagePoll.CONSTRUCTOR: this.inputMessageContent = new InputMessagePoll(input); break;
					case InputMessageForwarded.CONSTRUCTOR: this.inputMessageContent = new InputMessageForwarded(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputInlineQueryResultArticle.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputInlineQueryResultArticle.CONSTRUCTOR);
			if (this.id == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] idTmp = this.id.getBytes(StandardCharsets.UTF_8);
				output.writeInt(idTmp.length);
				output.write(idTmp);
			}
			if (this.url == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] urlTmp = this.url.getBytes(StandardCharsets.UTF_8);
				output.writeInt(urlTmp.length);
				output.write(urlTmp);
			}
			output.writeBoolean(this.hideUrl);
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
			if (this.description == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] descriptionTmp = this.description.getBytes(StandardCharsets.UTF_8);
				output.writeInt(descriptionTmp.length);
				output.write(descriptionTmp);
			}
			if (this.thumbnailUrl == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] thumbnailUrlTmp = this.thumbnailUrl.getBytes(StandardCharsets.UTF_8);
				output.writeInt(thumbnailUrlTmp.length);
				output.write(thumbnailUrlTmp);
			}
			output.writeInt(this.thumbnailWidth);
			output.writeInt(this.thumbnailHeight);
			if (this.replyMarkup == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.replyMarkup.serialize(output);
			}
			if (this.inputMessageContent == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.inputMessageContent.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputInlineQueryResultArticle inputInlineQueryResultArticle = (InputInlineQueryResultArticle) o;
			if (this.id != inputInlineQueryResultArticle.id) {
				return false;
			}
			if (this.url != inputInlineQueryResultArticle.url) {
				return false;
			}
			if (this.hideUrl != inputInlineQueryResultArticle.hideUrl) {
				return false;
			}
			if (this.title != inputInlineQueryResultArticle.title) {
				return false;
			}
			if (this.description != inputInlineQueryResultArticle.description) {
				return false;
			}
			if (this.thumbnailUrl != inputInlineQueryResultArticle.thumbnailUrl) {
				return false;
			}
			if (this.thumbnailWidth != inputInlineQueryResultArticle.thumbnailWidth) {
				return false;
			}
			if (this.thumbnailHeight != inputInlineQueryResultArticle.thumbnailHeight) {
				return false;
			}
			if (!Objects.equals(this.replyMarkup, inputInlineQueryResultArticle.replyMarkup)) {
				return false;
			}
			if (!Objects.equals(this.inputMessageContent, inputInlineQueryResultArticle.inputMessageContent)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.hideUrl);
			result = result * 31 + (this.id == null ? 0 : this.id.hashCode());
			result = result * 31 + (this.url == null ? 0 : this.url.hashCode());
			result = result * 31 + (this.title == null ? 0 : this.title.hashCode());
			result = result * 31 + (this.description == null ? 0 : this.description.hashCode());
			result = result * 31 + (this.thumbnailUrl == null ? 0 : this.thumbnailUrl.hashCode());
			result = result * 31 + (this.replyMarkup == null ? 0 : this.replyMarkup.hashCode());
			result = result * 31 + (this.inputMessageContent == null ? 0 : this.inputMessageContent.hashCode());
			return result;
		}
	}

	/**
	 * Represents a link to an MP3 audio file.
	**/
	public static final class InputInlineQueryResultAudio extends InputInlineQueryResult {


		/**
		 * Unique identifier of the query result.
		**/
		public String id;

		/**
		 * Title of the audio file.
		**/
		public String title;

		/**
		 * Performer of the audio file.
		**/
		public String performer;

		/**
		 * The URL of the audio file.
		**/
		public String audioUrl;

		/**
		 * Audio file duration, in seconds.
		**/
		public int audioDuration;

		/**
		 * The message reply markup; pass null if none. Must be of type replyMarkupInlineKeyboard or null.
		**/
		public ReplyMarkup replyMarkup;

		/**
		 * The content of the message to be sent. Must be one of the following types: inputMessageText, inputMessageAudio, inputMessageInvoice, inputMessageLocation, inputMessageVenue or inputMessageContact.
		**/
		public InputMessageContent inputMessageContent;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1260139988;

		/**
		 * Represents a link to an MP3 audio file.
		**/
		public InputInlineQueryResultAudio() {}

		/**
		 * Represents a link to an MP3 audio file.
		 *
		 * @param id Unique identifier of the query result.
		 * @param title Title of the audio file.
		 * @param performer Performer of the audio file.
		 * @param audioUrl The URL of the audio file.
		 * @param audioDuration Audio file duration, in seconds.
		 * @param replyMarkup The message reply markup; pass null if none. Must be of type replyMarkupInlineKeyboard or null.
		 * @param inputMessageContent The content of the message to be sent. Must be one of the following types: inputMessageText, inputMessageAudio, inputMessageInvoice, inputMessageLocation, inputMessageVenue or inputMessageContact.
		**/
		public InputInlineQueryResultAudio(String id,
				String title,
				String performer,
				String audioUrl,
				int audioDuration,
				ReplyMarkup replyMarkup,
				InputMessageContent inputMessageContent) {
			this.id = id;
			this.title = title;
			this.performer = performer;
			this.audioUrl = audioUrl;
			this.audioDuration = audioDuration;
			this.replyMarkup = replyMarkup;
			this.inputMessageContent = inputMessageContent;
		}

		/**
		 * Represents a link to an MP3 audio file.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputInlineQueryResultAudio(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] idTmp = new byte[input.readInt()];
				input.readFully(idTmp);
				this.id = new String(idTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] performerTmp = new byte[input.readInt()];
				input.readFully(performerTmp);
				this.performer = new String(performerTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] audioUrlTmp = new byte[input.readInt()];
				input.readFully(audioUrlTmp);
				this.audioUrl = new String(audioUrlTmp, StandardCharsets.UTF_8);
			}
			this.audioDuration = input.readInt();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ReplyMarkupRemoveKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupRemoveKeyboard(input); break;
					case ReplyMarkupForceReply.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupForceReply(input); break;
					case ReplyMarkupShowKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupShowKeyboard(input); break;
					case ReplyMarkupInlineKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupInlineKeyboard(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputMessageText.CONSTRUCTOR: this.inputMessageContent = new InputMessageText(input); break;
					case InputMessageAnimation.CONSTRUCTOR: this.inputMessageContent = new InputMessageAnimation(input); break;
					case InputMessageAudio.CONSTRUCTOR: this.inputMessageContent = new InputMessageAudio(input); break;
					case InputMessageDocument.CONSTRUCTOR: this.inputMessageContent = new InputMessageDocument(input); break;
					case InputMessagePhoto.CONSTRUCTOR: this.inputMessageContent = new InputMessagePhoto(input); break;
					case InputMessageSticker.CONSTRUCTOR: this.inputMessageContent = new InputMessageSticker(input); break;
					case InputMessageVideo.CONSTRUCTOR: this.inputMessageContent = new InputMessageVideo(input); break;
					case InputMessageVideoNote.CONSTRUCTOR: this.inputMessageContent = new InputMessageVideoNote(input); break;
					case InputMessageVoiceNote.CONSTRUCTOR: this.inputMessageContent = new InputMessageVoiceNote(input); break;
					case InputMessageLocation.CONSTRUCTOR: this.inputMessageContent = new InputMessageLocation(input); break;
					case InputMessageVenue.CONSTRUCTOR: this.inputMessageContent = new InputMessageVenue(input); break;
					case InputMessageContact.CONSTRUCTOR: this.inputMessageContent = new InputMessageContact(input); break;
					case InputMessageDice.CONSTRUCTOR: this.inputMessageContent = new InputMessageDice(input); break;
					case InputMessageGame.CONSTRUCTOR: this.inputMessageContent = new InputMessageGame(input); break;
					case InputMessageInvoice.CONSTRUCTOR: this.inputMessageContent = new InputMessageInvoice(input); break;
					case InputMessagePoll.CONSTRUCTOR: this.inputMessageContent = new InputMessagePoll(input); break;
					case InputMessageForwarded.CONSTRUCTOR: this.inputMessageContent = new InputMessageForwarded(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputInlineQueryResultAudio.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputInlineQueryResultAudio.CONSTRUCTOR);
			if (this.id == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] idTmp = this.id.getBytes(StandardCharsets.UTF_8);
				output.writeInt(idTmp.length);
				output.write(idTmp);
			}
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
			if (this.performer == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] performerTmp = this.performer.getBytes(StandardCharsets.UTF_8);
				output.writeInt(performerTmp.length);
				output.write(performerTmp);
			}
			if (this.audioUrl == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] audioUrlTmp = this.audioUrl.getBytes(StandardCharsets.UTF_8);
				output.writeInt(audioUrlTmp.length);
				output.write(audioUrlTmp);
			}
			output.writeInt(this.audioDuration);
			if (this.replyMarkup == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.replyMarkup.serialize(output);
			}
			if (this.inputMessageContent == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.inputMessageContent.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputInlineQueryResultAudio inputInlineQueryResultAudio = (InputInlineQueryResultAudio) o;
			if (this.id != inputInlineQueryResultAudio.id) {
				return false;
			}
			if (this.title != inputInlineQueryResultAudio.title) {
				return false;
			}
			if (this.performer != inputInlineQueryResultAudio.performer) {
				return false;
			}
			if (this.audioUrl != inputInlineQueryResultAudio.audioUrl) {
				return false;
			}
			if (this.audioDuration != inputInlineQueryResultAudio.audioDuration) {
				return false;
			}
			if (!Objects.equals(this.replyMarkup, inputInlineQueryResultAudio.replyMarkup)) {
				return false;
			}
			if (!Objects.equals(this.inputMessageContent, inputInlineQueryResultAudio.inputMessageContent)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.audioDuration);
			result = result * 31 + (this.id == null ? 0 : this.id.hashCode());
			result = result * 31 + (this.title == null ? 0 : this.title.hashCode());
			result = result * 31 + (this.performer == null ? 0 : this.performer.hashCode());
			result = result * 31 + (this.audioUrl == null ? 0 : this.audioUrl.hashCode());
			result = result * 31 + (this.replyMarkup == null ? 0 : this.replyMarkup.hashCode());
			result = result * 31 + (this.inputMessageContent == null ? 0 : this.inputMessageContent.hashCode());
			return result;
		}
	}

	/**
	 * Represents a user contact.
	**/
	public static final class InputInlineQueryResultContact extends InputInlineQueryResult {


		/**
		 * Unique identifier of the query result.
		**/
		public String id;

		/**
		 * User contact.
		**/
		public Contact contact;

		/**
		 * URL of the result thumbnail, if it exists.
		**/
		public String thumbnailUrl;

		/**
		 * Thumbnail width, if known.
		**/
		public int thumbnailWidth;

		/**
		 * Thumbnail height, if known.
		**/
		public int thumbnailHeight;

		/**
		 * The message reply markup; pass null if none. Must be of type replyMarkupInlineKeyboard or null.
		**/
		public ReplyMarkup replyMarkup;

		/**
		 * The content of the message to be sent. Must be one of the following types: inputMessageText, inputMessageInvoice, inputMessageLocation, inputMessageVenue or inputMessageContact.
		**/
		public InputMessageContent inputMessageContent;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1846064594;

		/**
		 * Represents a user contact.
		**/
		public InputInlineQueryResultContact() {}

		/**
		 * Represents a user contact.
		 *
		 * @param id Unique identifier of the query result.
		 * @param contact User contact.
		 * @param thumbnailUrl URL of the result thumbnail, if it exists.
		 * @param thumbnailWidth Thumbnail width, if known.
		 * @param thumbnailHeight Thumbnail height, if known.
		 * @param replyMarkup The message reply markup; pass null if none. Must be of type replyMarkupInlineKeyboard or null.
		 * @param inputMessageContent The content of the message to be sent. Must be one of the following types: inputMessageText, inputMessageInvoice, inputMessageLocation, inputMessageVenue or inputMessageContact.
		**/
		public InputInlineQueryResultContact(String id,
				Contact contact,
				String thumbnailUrl,
				int thumbnailWidth,
				int thumbnailHeight,
				ReplyMarkup replyMarkup,
				InputMessageContent inputMessageContent) {
			this.id = id;
			this.contact = contact;
			this.thumbnailUrl = thumbnailUrl;
			this.thumbnailWidth = thumbnailWidth;
			this.thumbnailHeight = thumbnailHeight;
			this.replyMarkup = replyMarkup;
			this.inputMessageContent = inputMessageContent;
		}

		/**
		 * Represents a user contact.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputInlineQueryResultContact(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] idTmp = new byte[input.readInt()];
				input.readFully(idTmp);
				this.id = new String(idTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (Contact.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.contact = new Contact(input);
			}
			if (input.readBoolean()) {
				byte[] thumbnailUrlTmp = new byte[input.readInt()];
				input.readFully(thumbnailUrlTmp);
				this.thumbnailUrl = new String(thumbnailUrlTmp, StandardCharsets.UTF_8);
			}
			this.thumbnailWidth = input.readInt();
			this.thumbnailHeight = input.readInt();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ReplyMarkupRemoveKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupRemoveKeyboard(input); break;
					case ReplyMarkupForceReply.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupForceReply(input); break;
					case ReplyMarkupShowKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupShowKeyboard(input); break;
					case ReplyMarkupInlineKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupInlineKeyboard(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputMessageText.CONSTRUCTOR: this.inputMessageContent = new InputMessageText(input); break;
					case InputMessageAnimation.CONSTRUCTOR: this.inputMessageContent = new InputMessageAnimation(input); break;
					case InputMessageAudio.CONSTRUCTOR: this.inputMessageContent = new InputMessageAudio(input); break;
					case InputMessageDocument.CONSTRUCTOR: this.inputMessageContent = new InputMessageDocument(input); break;
					case InputMessagePhoto.CONSTRUCTOR: this.inputMessageContent = new InputMessagePhoto(input); break;
					case InputMessageSticker.CONSTRUCTOR: this.inputMessageContent = new InputMessageSticker(input); break;
					case InputMessageVideo.CONSTRUCTOR: this.inputMessageContent = new InputMessageVideo(input); break;
					case InputMessageVideoNote.CONSTRUCTOR: this.inputMessageContent = new InputMessageVideoNote(input); break;
					case InputMessageVoiceNote.CONSTRUCTOR: this.inputMessageContent = new InputMessageVoiceNote(input); break;
					case InputMessageLocation.CONSTRUCTOR: this.inputMessageContent = new InputMessageLocation(input); break;
					case InputMessageVenue.CONSTRUCTOR: this.inputMessageContent = new InputMessageVenue(input); break;
					case InputMessageContact.CONSTRUCTOR: this.inputMessageContent = new InputMessageContact(input); break;
					case InputMessageDice.CONSTRUCTOR: this.inputMessageContent = new InputMessageDice(input); break;
					case InputMessageGame.CONSTRUCTOR: this.inputMessageContent = new InputMessageGame(input); break;
					case InputMessageInvoice.CONSTRUCTOR: this.inputMessageContent = new InputMessageInvoice(input); break;
					case InputMessagePoll.CONSTRUCTOR: this.inputMessageContent = new InputMessagePoll(input); break;
					case InputMessageForwarded.CONSTRUCTOR: this.inputMessageContent = new InputMessageForwarded(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputInlineQueryResultContact.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputInlineQueryResultContact.CONSTRUCTOR);
			if (this.id == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] idTmp = this.id.getBytes(StandardCharsets.UTF_8);
				output.writeInt(idTmp.length);
				output.write(idTmp);
			}
			if (this.contact == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.contact.serialize(output);
			}
			if (this.thumbnailUrl == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] thumbnailUrlTmp = this.thumbnailUrl.getBytes(StandardCharsets.UTF_8);
				output.writeInt(thumbnailUrlTmp.length);
				output.write(thumbnailUrlTmp);
			}
			output.writeInt(this.thumbnailWidth);
			output.writeInt(this.thumbnailHeight);
			if (this.replyMarkup == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.replyMarkup.serialize(output);
			}
			if (this.inputMessageContent == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.inputMessageContent.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputInlineQueryResultContact inputInlineQueryResultContact = (InputInlineQueryResultContact) o;
			if (this.id != inputInlineQueryResultContact.id) {
				return false;
			}
			if (!Objects.equals(this.contact, inputInlineQueryResultContact.contact)) {
				return false;
			}
			if (this.thumbnailUrl != inputInlineQueryResultContact.thumbnailUrl) {
				return false;
			}
			if (this.thumbnailWidth != inputInlineQueryResultContact.thumbnailWidth) {
				return false;
			}
			if (this.thumbnailHeight != inputInlineQueryResultContact.thumbnailHeight) {
				return false;
			}
			if (!Objects.equals(this.replyMarkup, inputInlineQueryResultContact.replyMarkup)) {
				return false;
			}
			if (!Objects.equals(this.inputMessageContent, inputInlineQueryResultContact.inputMessageContent)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.thumbnailWidth);
			result = result * 31 + (this.id == null ? 0 : this.id.hashCode());
			result = result * 31 + (this.contact == null ? 0 : this.contact.hashCode());
			result = result * 31 + (this.thumbnailUrl == null ? 0 : this.thumbnailUrl.hashCode());
			result = result * 31 + (this.replyMarkup == null ? 0 : this.replyMarkup.hashCode());
			result = result * 31 + (this.inputMessageContent == null ? 0 : this.inputMessageContent.hashCode());
			return result;
		}
	}

	/**
	 * Represents a link to a file.
	**/
	public static final class InputInlineQueryResultDocument extends InputInlineQueryResult {


		/**
		 * Unique identifier of the query result.
		**/
		public String id;

		/**
		 * Title of the resulting file.
		**/
		public String title;

		/**
		 * Short description of the result, if known.
		**/
		public String description;

		/**
		 * URL of the file.
		**/
		public String documentUrl;

		/**
		 * MIME type of the file content; only &quot;application/pdf&quot; and &quot;application/zip&quot; are currently allowed.
		**/
		public String mimeType;

		/**
		 * The URL of the file thumbnail, if it exists.
		**/
		public String thumbnailUrl;

		/**
		 * Width of the thumbnail.
		**/
		public int thumbnailWidth;

		/**
		 * Height of the thumbnail.
		**/
		public int thumbnailHeight;

		/**
		 * The message reply markup; pass null if none. Must be of type replyMarkupInlineKeyboard or null.
		**/
		public ReplyMarkup replyMarkup;

		/**
		 * The content of the message to be sent. Must be one of the following types: inputMessageText, inputMessageDocument, inputMessageInvoice, inputMessageLocation, inputMessageVenue or inputMessageContact.
		**/
		public InputMessageContent inputMessageContent;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 578801869;

		/**
		 * Represents a link to a file.
		**/
		public InputInlineQueryResultDocument() {}

		/**
		 * Represents a link to a file.
		 *
		 * @param id Unique identifier of the query result.
		 * @param title Title of the resulting file.
		 * @param description Short description of the result, if known.
		 * @param documentUrl URL of the file.
		 * @param mimeType MIME type of the file content; only &quot;application/pdf&quot; and &quot;application/zip&quot; are currently allowed.
		 * @param thumbnailUrl The URL of the file thumbnail, if it exists.
		 * @param thumbnailWidth Width of the thumbnail.
		 * @param thumbnailHeight Height of the thumbnail.
		 * @param replyMarkup The message reply markup; pass null if none. Must be of type replyMarkupInlineKeyboard or null.
		 * @param inputMessageContent The content of the message to be sent. Must be one of the following types: inputMessageText, inputMessageDocument, inputMessageInvoice, inputMessageLocation, inputMessageVenue or inputMessageContact.
		**/
		public InputInlineQueryResultDocument(String id,
				String title,
				String description,
				String documentUrl,
				String mimeType,
				String thumbnailUrl,
				int thumbnailWidth,
				int thumbnailHeight,
				ReplyMarkup replyMarkup,
				InputMessageContent inputMessageContent) {
			this.id = id;
			this.title = title;
			this.description = description;
			this.documentUrl = documentUrl;
			this.mimeType = mimeType;
			this.thumbnailUrl = thumbnailUrl;
			this.thumbnailWidth = thumbnailWidth;
			this.thumbnailHeight = thumbnailHeight;
			this.replyMarkup = replyMarkup;
			this.inputMessageContent = inputMessageContent;
		}

		/**
		 * Represents a link to a file.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputInlineQueryResultDocument(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] idTmp = new byte[input.readInt()];
				input.readFully(idTmp);
				this.id = new String(idTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] descriptionTmp = new byte[input.readInt()];
				input.readFully(descriptionTmp);
				this.description = new String(descriptionTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] documentUrlTmp = new byte[input.readInt()];
				input.readFully(documentUrlTmp);
				this.documentUrl = new String(documentUrlTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] mimeTypeTmp = new byte[input.readInt()];
				input.readFully(mimeTypeTmp);
				this.mimeType = new String(mimeTypeTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] thumbnailUrlTmp = new byte[input.readInt()];
				input.readFully(thumbnailUrlTmp);
				this.thumbnailUrl = new String(thumbnailUrlTmp, StandardCharsets.UTF_8);
			}
			this.thumbnailWidth = input.readInt();
			this.thumbnailHeight = input.readInt();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ReplyMarkupRemoveKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupRemoveKeyboard(input); break;
					case ReplyMarkupForceReply.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupForceReply(input); break;
					case ReplyMarkupShowKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupShowKeyboard(input); break;
					case ReplyMarkupInlineKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupInlineKeyboard(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputMessageText.CONSTRUCTOR: this.inputMessageContent = new InputMessageText(input); break;
					case InputMessageAnimation.CONSTRUCTOR: this.inputMessageContent = new InputMessageAnimation(input); break;
					case InputMessageAudio.CONSTRUCTOR: this.inputMessageContent = new InputMessageAudio(input); break;
					case InputMessageDocument.CONSTRUCTOR: this.inputMessageContent = new InputMessageDocument(input); break;
					case InputMessagePhoto.CONSTRUCTOR: this.inputMessageContent = new InputMessagePhoto(input); break;
					case InputMessageSticker.CONSTRUCTOR: this.inputMessageContent = new InputMessageSticker(input); break;
					case InputMessageVideo.CONSTRUCTOR: this.inputMessageContent = new InputMessageVideo(input); break;
					case InputMessageVideoNote.CONSTRUCTOR: this.inputMessageContent = new InputMessageVideoNote(input); break;
					case InputMessageVoiceNote.CONSTRUCTOR: this.inputMessageContent = new InputMessageVoiceNote(input); break;
					case InputMessageLocation.CONSTRUCTOR: this.inputMessageContent = new InputMessageLocation(input); break;
					case InputMessageVenue.CONSTRUCTOR: this.inputMessageContent = new InputMessageVenue(input); break;
					case InputMessageContact.CONSTRUCTOR: this.inputMessageContent = new InputMessageContact(input); break;
					case InputMessageDice.CONSTRUCTOR: this.inputMessageContent = new InputMessageDice(input); break;
					case InputMessageGame.CONSTRUCTOR: this.inputMessageContent = new InputMessageGame(input); break;
					case InputMessageInvoice.CONSTRUCTOR: this.inputMessageContent = new InputMessageInvoice(input); break;
					case InputMessagePoll.CONSTRUCTOR: this.inputMessageContent = new InputMessagePoll(input); break;
					case InputMessageForwarded.CONSTRUCTOR: this.inputMessageContent = new InputMessageForwarded(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputInlineQueryResultDocument.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputInlineQueryResultDocument.CONSTRUCTOR);
			if (this.id == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] idTmp = this.id.getBytes(StandardCharsets.UTF_8);
				output.writeInt(idTmp.length);
				output.write(idTmp);
			}
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
			if (this.description == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] descriptionTmp = this.description.getBytes(StandardCharsets.UTF_8);
				output.writeInt(descriptionTmp.length);
				output.write(descriptionTmp);
			}
			if (this.documentUrl == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] documentUrlTmp = this.documentUrl.getBytes(StandardCharsets.UTF_8);
				output.writeInt(documentUrlTmp.length);
				output.write(documentUrlTmp);
			}
			if (this.mimeType == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] mimeTypeTmp = this.mimeType.getBytes(StandardCharsets.UTF_8);
				output.writeInt(mimeTypeTmp.length);
				output.write(mimeTypeTmp);
			}
			if (this.thumbnailUrl == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] thumbnailUrlTmp = this.thumbnailUrl.getBytes(StandardCharsets.UTF_8);
				output.writeInt(thumbnailUrlTmp.length);
				output.write(thumbnailUrlTmp);
			}
			output.writeInt(this.thumbnailWidth);
			output.writeInt(this.thumbnailHeight);
			if (this.replyMarkup == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.replyMarkup.serialize(output);
			}
			if (this.inputMessageContent == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.inputMessageContent.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputInlineQueryResultDocument inputInlineQueryResultDocument = (InputInlineQueryResultDocument) o;
			if (this.id != inputInlineQueryResultDocument.id) {
				return false;
			}
			if (this.title != inputInlineQueryResultDocument.title) {
				return false;
			}
			if (this.description != inputInlineQueryResultDocument.description) {
				return false;
			}
			if (this.documentUrl != inputInlineQueryResultDocument.documentUrl) {
				return false;
			}
			if (this.mimeType != inputInlineQueryResultDocument.mimeType) {
				return false;
			}
			if (this.thumbnailUrl != inputInlineQueryResultDocument.thumbnailUrl) {
				return false;
			}
			if (this.thumbnailWidth != inputInlineQueryResultDocument.thumbnailWidth) {
				return false;
			}
			if (this.thumbnailHeight != inputInlineQueryResultDocument.thumbnailHeight) {
				return false;
			}
			if (!Objects.equals(this.replyMarkup, inputInlineQueryResultDocument.replyMarkup)) {
				return false;
			}
			if (!Objects.equals(this.inputMessageContent, inputInlineQueryResultDocument.inputMessageContent)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.thumbnailWidth);
			result = result * 31 + (this.id == null ? 0 : this.id.hashCode());
			result = result * 31 + (this.title == null ? 0 : this.title.hashCode());
			result = result * 31 + (this.description == null ? 0 : this.description.hashCode());
			result = result * 31 + (this.documentUrl == null ? 0 : this.documentUrl.hashCode());
			result = result * 31 + (this.mimeType == null ? 0 : this.mimeType.hashCode());
			result = result * 31 + (this.thumbnailUrl == null ? 0 : this.thumbnailUrl.hashCode());
			result = result * 31 + (this.replyMarkup == null ? 0 : this.replyMarkup.hashCode());
			result = result * 31 + (this.inputMessageContent == null ? 0 : this.inputMessageContent.hashCode());
			return result;
		}
	}

	/**
	 * Represents a game.
	**/
	public static final class InputInlineQueryResultGame extends InputInlineQueryResult {


		/**
		 * Unique identifier of the query result.
		**/
		public String id;

		/**
		 * Short name of the game.
		**/
		public String gameShortName;

		/**
		 * The message reply markup; pass null if none. Must be of type replyMarkupInlineKeyboard or null.
		**/
		public ReplyMarkup replyMarkup;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 966074327;

		/**
		 * Represents a game.
		**/
		public InputInlineQueryResultGame() {}

		/**
		 * Represents a game.
		 *
		 * @param id Unique identifier of the query result.
		 * @param gameShortName Short name of the game.
		 * @param replyMarkup The message reply markup; pass null if none. Must be of type replyMarkupInlineKeyboard or null.
		**/
		public InputInlineQueryResultGame(String id, String gameShortName, ReplyMarkup replyMarkup) {
			this.id = id;
			this.gameShortName = gameShortName;
			this.replyMarkup = replyMarkup;
		}

		/**
		 * Represents a game.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputInlineQueryResultGame(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] idTmp = new byte[input.readInt()];
				input.readFully(idTmp);
				this.id = new String(idTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] gameShortNameTmp = new byte[input.readInt()];
				input.readFully(gameShortNameTmp);
				this.gameShortName = new String(gameShortNameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ReplyMarkupRemoveKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupRemoveKeyboard(input); break;
					case ReplyMarkupForceReply.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupForceReply(input); break;
					case ReplyMarkupShowKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupShowKeyboard(input); break;
					case ReplyMarkupInlineKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupInlineKeyboard(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputInlineQueryResultGame.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputInlineQueryResultGame.CONSTRUCTOR);
			if (this.id == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] idTmp = this.id.getBytes(StandardCharsets.UTF_8);
				output.writeInt(idTmp.length);
				output.write(idTmp);
			}
			if (this.gameShortName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] gameShortNameTmp = this.gameShortName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(gameShortNameTmp.length);
				output.write(gameShortNameTmp);
			}
			if (this.replyMarkup == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.replyMarkup.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputInlineQueryResultGame inputInlineQueryResultGame = (InputInlineQueryResultGame) o;
			if (this.id != inputInlineQueryResultGame.id) {
				return false;
			}
			if (this.gameShortName != inputInlineQueryResultGame.gameShortName) {
				return false;
			}
			if (!Objects.equals(this.replyMarkup, inputInlineQueryResultGame.replyMarkup)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.id == null ? 0 : this.id.hashCode();
			result = result * 31 + (this.gameShortName == null ? 0 : this.gameShortName.hashCode());
			result = result * 31 + (this.replyMarkup == null ? 0 : this.replyMarkup.hashCode());
			return result;
		}
	}

	/**
	 * Represents a point on the map.
	**/
	public static final class InputInlineQueryResultLocation extends InputInlineQueryResult {


		/**
		 * Unique identifier of the query result.
		**/
		public String id;

		/**
		 * Location result.
		**/
		public Location location;

		/**
		 * Amount of time relative to the message sent time until the location can be updated, in seconds.
		**/
		public int livePeriod;

		/**
		 * Title of the result.
		**/
		public String title;

		/**
		 * URL of the result thumbnail, if it exists.
		**/
		public String thumbnailUrl;

		/**
		 * Thumbnail width, if known.
		**/
		public int thumbnailWidth;

		/**
		 * Thumbnail height, if known.
		**/
		public int thumbnailHeight;

		/**
		 * The message reply markup; pass null if none. Must be of type replyMarkupInlineKeyboard or null.
		**/
		public ReplyMarkup replyMarkup;

		/**
		 * The content of the message to be sent. Must be one of the following types: inputMessageText, inputMessageInvoice, inputMessageLocation, inputMessageVenue or inputMessageContact.
		**/
		public InputMessageContent inputMessageContent;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1887650218;

		/**
		 * Represents a point on the map.
		**/
		public InputInlineQueryResultLocation() {}

		/**
		 * Represents a point on the map.
		 *
		 * @param id Unique identifier of the query result.
		 * @param location Location result.
		 * @param livePeriod Amount of time relative to the message sent time until the location can be updated, in seconds.
		 * @param title Title of the result.
		 * @param thumbnailUrl URL of the result thumbnail, if it exists.
		 * @param thumbnailWidth Thumbnail width, if known.
		 * @param thumbnailHeight Thumbnail height, if known.
		 * @param replyMarkup The message reply markup; pass null if none. Must be of type replyMarkupInlineKeyboard or null.
		 * @param inputMessageContent The content of the message to be sent. Must be one of the following types: inputMessageText, inputMessageInvoice, inputMessageLocation, inputMessageVenue or inputMessageContact.
		**/
		public InputInlineQueryResultLocation(String id,
				Location location,
				int livePeriod,
				String title,
				String thumbnailUrl,
				int thumbnailWidth,
				int thumbnailHeight,
				ReplyMarkup replyMarkup,
				InputMessageContent inputMessageContent) {
			this.id = id;
			this.location = location;
			this.livePeriod = livePeriod;
			this.title = title;
			this.thumbnailUrl = thumbnailUrl;
			this.thumbnailWidth = thumbnailWidth;
			this.thumbnailHeight = thumbnailHeight;
			this.replyMarkup = replyMarkup;
			this.inputMessageContent = inputMessageContent;
		}

		/**
		 * Represents a point on the map.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputInlineQueryResultLocation(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] idTmp = new byte[input.readInt()];
				input.readFully(idTmp);
				this.id = new String(idTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (Location.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.location = new Location(input);
			}
			this.livePeriod = input.readInt();
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] thumbnailUrlTmp = new byte[input.readInt()];
				input.readFully(thumbnailUrlTmp);
				this.thumbnailUrl = new String(thumbnailUrlTmp, StandardCharsets.UTF_8);
			}
			this.thumbnailWidth = input.readInt();
			this.thumbnailHeight = input.readInt();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ReplyMarkupRemoveKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupRemoveKeyboard(input); break;
					case ReplyMarkupForceReply.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupForceReply(input); break;
					case ReplyMarkupShowKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupShowKeyboard(input); break;
					case ReplyMarkupInlineKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupInlineKeyboard(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputMessageText.CONSTRUCTOR: this.inputMessageContent = new InputMessageText(input); break;
					case InputMessageAnimation.CONSTRUCTOR: this.inputMessageContent = new InputMessageAnimation(input); break;
					case InputMessageAudio.CONSTRUCTOR: this.inputMessageContent = new InputMessageAudio(input); break;
					case InputMessageDocument.CONSTRUCTOR: this.inputMessageContent = new InputMessageDocument(input); break;
					case InputMessagePhoto.CONSTRUCTOR: this.inputMessageContent = new InputMessagePhoto(input); break;
					case InputMessageSticker.CONSTRUCTOR: this.inputMessageContent = new InputMessageSticker(input); break;
					case InputMessageVideo.CONSTRUCTOR: this.inputMessageContent = new InputMessageVideo(input); break;
					case InputMessageVideoNote.CONSTRUCTOR: this.inputMessageContent = new InputMessageVideoNote(input); break;
					case InputMessageVoiceNote.CONSTRUCTOR: this.inputMessageContent = new InputMessageVoiceNote(input); break;
					case InputMessageLocation.CONSTRUCTOR: this.inputMessageContent = new InputMessageLocation(input); break;
					case InputMessageVenue.CONSTRUCTOR: this.inputMessageContent = new InputMessageVenue(input); break;
					case InputMessageContact.CONSTRUCTOR: this.inputMessageContent = new InputMessageContact(input); break;
					case InputMessageDice.CONSTRUCTOR: this.inputMessageContent = new InputMessageDice(input); break;
					case InputMessageGame.CONSTRUCTOR: this.inputMessageContent = new InputMessageGame(input); break;
					case InputMessageInvoice.CONSTRUCTOR: this.inputMessageContent = new InputMessageInvoice(input); break;
					case InputMessagePoll.CONSTRUCTOR: this.inputMessageContent = new InputMessagePoll(input); break;
					case InputMessageForwarded.CONSTRUCTOR: this.inputMessageContent = new InputMessageForwarded(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputInlineQueryResultLocation.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputInlineQueryResultLocation.CONSTRUCTOR);
			if (this.id == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] idTmp = this.id.getBytes(StandardCharsets.UTF_8);
				output.writeInt(idTmp.length);
				output.write(idTmp);
			}
			if (this.location == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.location.serialize(output);
			}
			output.writeInt(this.livePeriod);
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
			if (this.thumbnailUrl == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] thumbnailUrlTmp = this.thumbnailUrl.getBytes(StandardCharsets.UTF_8);
				output.writeInt(thumbnailUrlTmp.length);
				output.write(thumbnailUrlTmp);
			}
			output.writeInt(this.thumbnailWidth);
			output.writeInt(this.thumbnailHeight);
			if (this.replyMarkup == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.replyMarkup.serialize(output);
			}
			if (this.inputMessageContent == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.inputMessageContent.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputInlineQueryResultLocation inputInlineQueryResultLocation = (InputInlineQueryResultLocation) o;
			if (this.id != inputInlineQueryResultLocation.id) {
				return false;
			}
			if (!Objects.equals(this.location, inputInlineQueryResultLocation.location)) {
				return false;
			}
			if (this.livePeriod != inputInlineQueryResultLocation.livePeriod) {
				return false;
			}
			if (this.title != inputInlineQueryResultLocation.title) {
				return false;
			}
			if (this.thumbnailUrl != inputInlineQueryResultLocation.thumbnailUrl) {
				return false;
			}
			if (this.thumbnailWidth != inputInlineQueryResultLocation.thumbnailWidth) {
				return false;
			}
			if (this.thumbnailHeight != inputInlineQueryResultLocation.thumbnailHeight) {
				return false;
			}
			if (!Objects.equals(this.replyMarkup, inputInlineQueryResultLocation.replyMarkup)) {
				return false;
			}
			if (!Objects.equals(this.inputMessageContent, inputInlineQueryResultLocation.inputMessageContent)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.livePeriod);
			result = result * 31 + (this.id == null ? 0 : this.id.hashCode());
			result = result * 31 + (this.location == null ? 0 : this.location.hashCode());
			result = result * 31 + (this.title == null ? 0 : this.title.hashCode());
			result = result * 31 + (this.thumbnailUrl == null ? 0 : this.thumbnailUrl.hashCode());
			result = result * 31 + (this.replyMarkup == null ? 0 : this.replyMarkup.hashCode());
			result = result * 31 + (this.inputMessageContent == null ? 0 : this.inputMessageContent.hashCode());
			return result;
		}
	}

	/**
	 * Represents link to a JPEG image.
	**/
	public static final class InputInlineQueryResultPhoto extends InputInlineQueryResult {


		/**
		 * Unique identifier of the query result.
		**/
		public String id;

		/**
		 * Title of the result, if known.
		**/
		public String title;

		/**
		 * A short description of the result, if known.
		**/
		public String description;

		/**
		 * URL of the photo thumbnail, if it exists.
		**/
		public String thumbnailUrl;

		/**
		 * The URL of the JPEG photo (photo size must not exceed 5MB).
		**/
		public String photoUrl;

		/**
		 * Width of the photo.
		**/
		public int photoWidth;

		/**
		 * Height of the photo.
		**/
		public int photoHeight;

		/**
		 * The message reply markup; pass null if none. Must be of type replyMarkupInlineKeyboard or null.
		**/
		public ReplyMarkup replyMarkup;

		/**
		 * The content of the message to be sent. Must be one of the following types: inputMessageText, inputMessagePhoto, inputMessageInvoice, inputMessageLocation, inputMessageVenue or inputMessageContact.
		**/
		public InputMessageContent inputMessageContent;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1123338721;

		/**
		 * Represents link to a JPEG image.
		**/
		public InputInlineQueryResultPhoto() {}

		/**
		 * Represents link to a JPEG image.
		 *
		 * @param id Unique identifier of the query result.
		 * @param title Title of the result, if known.
		 * @param description A short description of the result, if known.
		 * @param thumbnailUrl URL of the photo thumbnail, if it exists.
		 * @param photoUrl The URL of the JPEG photo (photo size must not exceed 5MB).
		 * @param photoWidth Width of the photo.
		 * @param photoHeight Height of the photo.
		 * @param replyMarkup The message reply markup; pass null if none. Must be of type replyMarkupInlineKeyboard or null.
		 * @param inputMessageContent The content of the message to be sent. Must be one of the following types: inputMessageText, inputMessagePhoto, inputMessageInvoice, inputMessageLocation, inputMessageVenue or inputMessageContact.
		**/
		public InputInlineQueryResultPhoto(String id,
				String title,
				String description,
				String thumbnailUrl,
				String photoUrl,
				int photoWidth,
				int photoHeight,
				ReplyMarkup replyMarkup,
				InputMessageContent inputMessageContent) {
			this.id = id;
			this.title = title;
			this.description = description;
			this.thumbnailUrl = thumbnailUrl;
			this.photoUrl = photoUrl;
			this.photoWidth = photoWidth;
			this.photoHeight = photoHeight;
			this.replyMarkup = replyMarkup;
			this.inputMessageContent = inputMessageContent;
		}

		/**
		 * Represents link to a JPEG image.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputInlineQueryResultPhoto(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] idTmp = new byte[input.readInt()];
				input.readFully(idTmp);
				this.id = new String(idTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] descriptionTmp = new byte[input.readInt()];
				input.readFully(descriptionTmp);
				this.description = new String(descriptionTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] thumbnailUrlTmp = new byte[input.readInt()];
				input.readFully(thumbnailUrlTmp);
				this.thumbnailUrl = new String(thumbnailUrlTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] photoUrlTmp = new byte[input.readInt()];
				input.readFully(photoUrlTmp);
				this.photoUrl = new String(photoUrlTmp, StandardCharsets.UTF_8);
			}
			this.photoWidth = input.readInt();
			this.photoHeight = input.readInt();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ReplyMarkupRemoveKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupRemoveKeyboard(input); break;
					case ReplyMarkupForceReply.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupForceReply(input); break;
					case ReplyMarkupShowKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupShowKeyboard(input); break;
					case ReplyMarkupInlineKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupInlineKeyboard(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputMessageText.CONSTRUCTOR: this.inputMessageContent = new InputMessageText(input); break;
					case InputMessageAnimation.CONSTRUCTOR: this.inputMessageContent = new InputMessageAnimation(input); break;
					case InputMessageAudio.CONSTRUCTOR: this.inputMessageContent = new InputMessageAudio(input); break;
					case InputMessageDocument.CONSTRUCTOR: this.inputMessageContent = new InputMessageDocument(input); break;
					case InputMessagePhoto.CONSTRUCTOR: this.inputMessageContent = new InputMessagePhoto(input); break;
					case InputMessageSticker.CONSTRUCTOR: this.inputMessageContent = new InputMessageSticker(input); break;
					case InputMessageVideo.CONSTRUCTOR: this.inputMessageContent = new InputMessageVideo(input); break;
					case InputMessageVideoNote.CONSTRUCTOR: this.inputMessageContent = new InputMessageVideoNote(input); break;
					case InputMessageVoiceNote.CONSTRUCTOR: this.inputMessageContent = new InputMessageVoiceNote(input); break;
					case InputMessageLocation.CONSTRUCTOR: this.inputMessageContent = new InputMessageLocation(input); break;
					case InputMessageVenue.CONSTRUCTOR: this.inputMessageContent = new InputMessageVenue(input); break;
					case InputMessageContact.CONSTRUCTOR: this.inputMessageContent = new InputMessageContact(input); break;
					case InputMessageDice.CONSTRUCTOR: this.inputMessageContent = new InputMessageDice(input); break;
					case InputMessageGame.CONSTRUCTOR: this.inputMessageContent = new InputMessageGame(input); break;
					case InputMessageInvoice.CONSTRUCTOR: this.inputMessageContent = new InputMessageInvoice(input); break;
					case InputMessagePoll.CONSTRUCTOR: this.inputMessageContent = new InputMessagePoll(input); break;
					case InputMessageForwarded.CONSTRUCTOR: this.inputMessageContent = new InputMessageForwarded(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputInlineQueryResultPhoto.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputInlineQueryResultPhoto.CONSTRUCTOR);
			if (this.id == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] idTmp = this.id.getBytes(StandardCharsets.UTF_8);
				output.writeInt(idTmp.length);
				output.write(idTmp);
			}
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
			if (this.description == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] descriptionTmp = this.description.getBytes(StandardCharsets.UTF_8);
				output.writeInt(descriptionTmp.length);
				output.write(descriptionTmp);
			}
			if (this.thumbnailUrl == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] thumbnailUrlTmp = this.thumbnailUrl.getBytes(StandardCharsets.UTF_8);
				output.writeInt(thumbnailUrlTmp.length);
				output.write(thumbnailUrlTmp);
			}
			if (this.photoUrl == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] photoUrlTmp = this.photoUrl.getBytes(StandardCharsets.UTF_8);
				output.writeInt(photoUrlTmp.length);
				output.write(photoUrlTmp);
			}
			output.writeInt(this.photoWidth);
			output.writeInt(this.photoHeight);
			if (this.replyMarkup == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.replyMarkup.serialize(output);
			}
			if (this.inputMessageContent == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.inputMessageContent.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputInlineQueryResultPhoto inputInlineQueryResultPhoto = (InputInlineQueryResultPhoto) o;
			if (this.id != inputInlineQueryResultPhoto.id) {
				return false;
			}
			if (this.title != inputInlineQueryResultPhoto.title) {
				return false;
			}
			if (this.description != inputInlineQueryResultPhoto.description) {
				return false;
			}
			if (this.thumbnailUrl != inputInlineQueryResultPhoto.thumbnailUrl) {
				return false;
			}
			if (this.photoUrl != inputInlineQueryResultPhoto.photoUrl) {
				return false;
			}
			if (this.photoWidth != inputInlineQueryResultPhoto.photoWidth) {
				return false;
			}
			if (this.photoHeight != inputInlineQueryResultPhoto.photoHeight) {
				return false;
			}
			if (!Objects.equals(this.replyMarkup, inputInlineQueryResultPhoto.replyMarkup)) {
				return false;
			}
			if (!Objects.equals(this.inputMessageContent, inputInlineQueryResultPhoto.inputMessageContent)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.photoWidth);
			result = result * 31 + (this.id == null ? 0 : this.id.hashCode());
			result = result * 31 + (this.title == null ? 0 : this.title.hashCode());
			result = result * 31 + (this.description == null ? 0 : this.description.hashCode());
			result = result * 31 + (this.thumbnailUrl == null ? 0 : this.thumbnailUrl.hashCode());
			result = result * 31 + (this.photoUrl == null ? 0 : this.photoUrl.hashCode());
			result = result * 31 + (this.replyMarkup == null ? 0 : this.replyMarkup.hashCode());
			result = result * 31 + (this.inputMessageContent == null ? 0 : this.inputMessageContent.hashCode());
			return result;
		}
	}

	/**
	 * Represents a link to a WEBP, TGS, or WEBM sticker.
	**/
	public static final class InputInlineQueryResultSticker extends InputInlineQueryResult {


		/**
		 * Unique identifier of the query result.
		**/
		public String id;

		/**
		 * URL of the sticker thumbnail, if it exists.
		**/
		public String thumbnailUrl;

		/**
		 * The URL of the WEBP, TGS, or WEBM sticker (sticker file size must not exceed 5MB).
		**/
		public String stickerUrl;

		/**
		 * Width of the sticker.
		**/
		public int stickerWidth;

		/**
		 * Height of the sticker.
		**/
		public int stickerHeight;

		/**
		 * The message reply markup; pass null if none. Must be of type replyMarkupInlineKeyboard or null.
		**/
		public ReplyMarkup replyMarkup;

		/**
		 * The content of the message to be sent. Must be one of the following types: inputMessageText, inputMessageSticker, inputMessageInvoice, inputMessageLocation, inputMessageVenue or inputMessageContact.
		**/
		public InputMessageContent inputMessageContent;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 274007129;

		/**
		 * Represents a link to a WEBP, TGS, or WEBM sticker.
		**/
		public InputInlineQueryResultSticker() {}

		/**
		 * Represents a link to a WEBP, TGS, or WEBM sticker.
		 *
		 * @param id Unique identifier of the query result.
		 * @param thumbnailUrl URL of the sticker thumbnail, if it exists.
		 * @param stickerUrl The URL of the WEBP, TGS, or WEBM sticker (sticker file size must not exceed 5MB).
		 * @param stickerWidth Width of the sticker.
		 * @param stickerHeight Height of the sticker.
		 * @param replyMarkup The message reply markup; pass null if none. Must be of type replyMarkupInlineKeyboard or null.
		 * @param inputMessageContent The content of the message to be sent. Must be one of the following types: inputMessageText, inputMessageSticker, inputMessageInvoice, inputMessageLocation, inputMessageVenue or inputMessageContact.
		**/
		public InputInlineQueryResultSticker(String id,
				String thumbnailUrl,
				String stickerUrl,
				int stickerWidth,
				int stickerHeight,
				ReplyMarkup replyMarkup,
				InputMessageContent inputMessageContent) {
			this.id = id;
			this.thumbnailUrl = thumbnailUrl;
			this.stickerUrl = stickerUrl;
			this.stickerWidth = stickerWidth;
			this.stickerHeight = stickerHeight;
			this.replyMarkup = replyMarkup;
			this.inputMessageContent = inputMessageContent;
		}

		/**
		 * Represents a link to a WEBP, TGS, or WEBM sticker.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputInlineQueryResultSticker(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] idTmp = new byte[input.readInt()];
				input.readFully(idTmp);
				this.id = new String(idTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] thumbnailUrlTmp = new byte[input.readInt()];
				input.readFully(thumbnailUrlTmp);
				this.thumbnailUrl = new String(thumbnailUrlTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] stickerUrlTmp = new byte[input.readInt()];
				input.readFully(stickerUrlTmp);
				this.stickerUrl = new String(stickerUrlTmp, StandardCharsets.UTF_8);
			}
			this.stickerWidth = input.readInt();
			this.stickerHeight = input.readInt();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ReplyMarkupRemoveKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupRemoveKeyboard(input); break;
					case ReplyMarkupForceReply.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupForceReply(input); break;
					case ReplyMarkupShowKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupShowKeyboard(input); break;
					case ReplyMarkupInlineKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupInlineKeyboard(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputMessageText.CONSTRUCTOR: this.inputMessageContent = new InputMessageText(input); break;
					case InputMessageAnimation.CONSTRUCTOR: this.inputMessageContent = new InputMessageAnimation(input); break;
					case InputMessageAudio.CONSTRUCTOR: this.inputMessageContent = new InputMessageAudio(input); break;
					case InputMessageDocument.CONSTRUCTOR: this.inputMessageContent = new InputMessageDocument(input); break;
					case InputMessagePhoto.CONSTRUCTOR: this.inputMessageContent = new InputMessagePhoto(input); break;
					case InputMessageSticker.CONSTRUCTOR: this.inputMessageContent = new InputMessageSticker(input); break;
					case InputMessageVideo.CONSTRUCTOR: this.inputMessageContent = new InputMessageVideo(input); break;
					case InputMessageVideoNote.CONSTRUCTOR: this.inputMessageContent = new InputMessageVideoNote(input); break;
					case InputMessageVoiceNote.CONSTRUCTOR: this.inputMessageContent = new InputMessageVoiceNote(input); break;
					case InputMessageLocation.CONSTRUCTOR: this.inputMessageContent = new InputMessageLocation(input); break;
					case InputMessageVenue.CONSTRUCTOR: this.inputMessageContent = new InputMessageVenue(input); break;
					case InputMessageContact.CONSTRUCTOR: this.inputMessageContent = new InputMessageContact(input); break;
					case InputMessageDice.CONSTRUCTOR: this.inputMessageContent = new InputMessageDice(input); break;
					case InputMessageGame.CONSTRUCTOR: this.inputMessageContent = new InputMessageGame(input); break;
					case InputMessageInvoice.CONSTRUCTOR: this.inputMessageContent = new InputMessageInvoice(input); break;
					case InputMessagePoll.CONSTRUCTOR: this.inputMessageContent = new InputMessagePoll(input); break;
					case InputMessageForwarded.CONSTRUCTOR: this.inputMessageContent = new InputMessageForwarded(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputInlineQueryResultSticker.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputInlineQueryResultSticker.CONSTRUCTOR);
			if (this.id == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] idTmp = this.id.getBytes(StandardCharsets.UTF_8);
				output.writeInt(idTmp.length);
				output.write(idTmp);
			}
			if (this.thumbnailUrl == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] thumbnailUrlTmp = this.thumbnailUrl.getBytes(StandardCharsets.UTF_8);
				output.writeInt(thumbnailUrlTmp.length);
				output.write(thumbnailUrlTmp);
			}
			if (this.stickerUrl == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] stickerUrlTmp = this.stickerUrl.getBytes(StandardCharsets.UTF_8);
				output.writeInt(stickerUrlTmp.length);
				output.write(stickerUrlTmp);
			}
			output.writeInt(this.stickerWidth);
			output.writeInt(this.stickerHeight);
			if (this.replyMarkup == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.replyMarkup.serialize(output);
			}
			if (this.inputMessageContent == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.inputMessageContent.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputInlineQueryResultSticker inputInlineQueryResultSticker = (InputInlineQueryResultSticker) o;
			if (this.id != inputInlineQueryResultSticker.id) {
				return false;
			}
			if (this.thumbnailUrl != inputInlineQueryResultSticker.thumbnailUrl) {
				return false;
			}
			if (this.stickerUrl != inputInlineQueryResultSticker.stickerUrl) {
				return false;
			}
			if (this.stickerWidth != inputInlineQueryResultSticker.stickerWidth) {
				return false;
			}
			if (this.stickerHeight != inputInlineQueryResultSticker.stickerHeight) {
				return false;
			}
			if (!Objects.equals(this.replyMarkup, inputInlineQueryResultSticker.replyMarkup)) {
				return false;
			}
			if (!Objects.equals(this.inputMessageContent, inputInlineQueryResultSticker.inputMessageContent)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.stickerWidth);
			result = result * 31 + (this.id == null ? 0 : this.id.hashCode());
			result = result * 31 + (this.thumbnailUrl == null ? 0 : this.thumbnailUrl.hashCode());
			result = result * 31 + (this.stickerUrl == null ? 0 : this.stickerUrl.hashCode());
			result = result * 31 + (this.replyMarkup == null ? 0 : this.replyMarkup.hashCode());
			result = result * 31 + (this.inputMessageContent == null ? 0 : this.inputMessageContent.hashCode());
			return result;
		}
	}

	/**
	 * Represents information about a venue.
	**/
	public static final class InputInlineQueryResultVenue extends InputInlineQueryResult {


		/**
		 * Unique identifier of the query result.
		**/
		public String id;

		/**
		 * Venue result.
		**/
		public Venue venue;

		/**
		 * URL of the result thumbnail, if it exists.
		**/
		public String thumbnailUrl;

		/**
		 * Thumbnail width, if known.
		**/
		public int thumbnailWidth;

		/**
		 * Thumbnail height, if known.
		**/
		public int thumbnailHeight;

		/**
		 * The message reply markup; pass null if none. Must be of type replyMarkupInlineKeyboard or null.
		**/
		public ReplyMarkup replyMarkup;

		/**
		 * The content of the message to be sent. Must be one of the following types: inputMessageText, inputMessageInvoice, inputMessageLocation, inputMessageVenue or inputMessageContact.
		**/
		public InputMessageContent inputMessageContent;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 541704509;

		/**
		 * Represents information about a venue.
		**/
		public InputInlineQueryResultVenue() {}

		/**
		 * Represents information about a venue.
		 *
		 * @param id Unique identifier of the query result.
		 * @param venue Venue result.
		 * @param thumbnailUrl URL of the result thumbnail, if it exists.
		 * @param thumbnailWidth Thumbnail width, if known.
		 * @param thumbnailHeight Thumbnail height, if known.
		 * @param replyMarkup The message reply markup; pass null if none. Must be of type replyMarkupInlineKeyboard or null.
		 * @param inputMessageContent The content of the message to be sent. Must be one of the following types: inputMessageText, inputMessageInvoice, inputMessageLocation, inputMessageVenue or inputMessageContact.
		**/
		public InputInlineQueryResultVenue(String id,
				Venue venue,
				String thumbnailUrl,
				int thumbnailWidth,
				int thumbnailHeight,
				ReplyMarkup replyMarkup,
				InputMessageContent inputMessageContent) {
			this.id = id;
			this.venue = venue;
			this.thumbnailUrl = thumbnailUrl;
			this.thumbnailWidth = thumbnailWidth;
			this.thumbnailHeight = thumbnailHeight;
			this.replyMarkup = replyMarkup;
			this.inputMessageContent = inputMessageContent;
		}

		/**
		 * Represents information about a venue.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputInlineQueryResultVenue(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] idTmp = new byte[input.readInt()];
				input.readFully(idTmp);
				this.id = new String(idTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (Venue.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.venue = new Venue(input);
			}
			if (input.readBoolean()) {
				byte[] thumbnailUrlTmp = new byte[input.readInt()];
				input.readFully(thumbnailUrlTmp);
				this.thumbnailUrl = new String(thumbnailUrlTmp, StandardCharsets.UTF_8);
			}
			this.thumbnailWidth = input.readInt();
			this.thumbnailHeight = input.readInt();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ReplyMarkupRemoveKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupRemoveKeyboard(input); break;
					case ReplyMarkupForceReply.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupForceReply(input); break;
					case ReplyMarkupShowKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupShowKeyboard(input); break;
					case ReplyMarkupInlineKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupInlineKeyboard(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputMessageText.CONSTRUCTOR: this.inputMessageContent = new InputMessageText(input); break;
					case InputMessageAnimation.CONSTRUCTOR: this.inputMessageContent = new InputMessageAnimation(input); break;
					case InputMessageAudio.CONSTRUCTOR: this.inputMessageContent = new InputMessageAudio(input); break;
					case InputMessageDocument.CONSTRUCTOR: this.inputMessageContent = new InputMessageDocument(input); break;
					case InputMessagePhoto.CONSTRUCTOR: this.inputMessageContent = new InputMessagePhoto(input); break;
					case InputMessageSticker.CONSTRUCTOR: this.inputMessageContent = new InputMessageSticker(input); break;
					case InputMessageVideo.CONSTRUCTOR: this.inputMessageContent = new InputMessageVideo(input); break;
					case InputMessageVideoNote.CONSTRUCTOR: this.inputMessageContent = new InputMessageVideoNote(input); break;
					case InputMessageVoiceNote.CONSTRUCTOR: this.inputMessageContent = new InputMessageVoiceNote(input); break;
					case InputMessageLocation.CONSTRUCTOR: this.inputMessageContent = new InputMessageLocation(input); break;
					case InputMessageVenue.CONSTRUCTOR: this.inputMessageContent = new InputMessageVenue(input); break;
					case InputMessageContact.CONSTRUCTOR: this.inputMessageContent = new InputMessageContact(input); break;
					case InputMessageDice.CONSTRUCTOR: this.inputMessageContent = new InputMessageDice(input); break;
					case InputMessageGame.CONSTRUCTOR: this.inputMessageContent = new InputMessageGame(input); break;
					case InputMessageInvoice.CONSTRUCTOR: this.inputMessageContent = new InputMessageInvoice(input); break;
					case InputMessagePoll.CONSTRUCTOR: this.inputMessageContent = new InputMessagePoll(input); break;
					case InputMessageForwarded.CONSTRUCTOR: this.inputMessageContent = new InputMessageForwarded(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputInlineQueryResultVenue.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputInlineQueryResultVenue.CONSTRUCTOR);
			if (this.id == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] idTmp = this.id.getBytes(StandardCharsets.UTF_8);
				output.writeInt(idTmp.length);
				output.write(idTmp);
			}
			if (this.venue == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.venue.serialize(output);
			}
			if (this.thumbnailUrl == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] thumbnailUrlTmp = this.thumbnailUrl.getBytes(StandardCharsets.UTF_8);
				output.writeInt(thumbnailUrlTmp.length);
				output.write(thumbnailUrlTmp);
			}
			output.writeInt(this.thumbnailWidth);
			output.writeInt(this.thumbnailHeight);
			if (this.replyMarkup == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.replyMarkup.serialize(output);
			}
			if (this.inputMessageContent == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.inputMessageContent.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputInlineQueryResultVenue inputInlineQueryResultVenue = (InputInlineQueryResultVenue) o;
			if (this.id != inputInlineQueryResultVenue.id) {
				return false;
			}
			if (!Objects.equals(this.venue, inputInlineQueryResultVenue.venue)) {
				return false;
			}
			if (this.thumbnailUrl != inputInlineQueryResultVenue.thumbnailUrl) {
				return false;
			}
			if (this.thumbnailWidth != inputInlineQueryResultVenue.thumbnailWidth) {
				return false;
			}
			if (this.thumbnailHeight != inputInlineQueryResultVenue.thumbnailHeight) {
				return false;
			}
			if (!Objects.equals(this.replyMarkup, inputInlineQueryResultVenue.replyMarkup)) {
				return false;
			}
			if (!Objects.equals(this.inputMessageContent, inputInlineQueryResultVenue.inputMessageContent)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.thumbnailWidth);
			result = result * 31 + (this.id == null ? 0 : this.id.hashCode());
			result = result * 31 + (this.venue == null ? 0 : this.venue.hashCode());
			result = result * 31 + (this.thumbnailUrl == null ? 0 : this.thumbnailUrl.hashCode());
			result = result * 31 + (this.replyMarkup == null ? 0 : this.replyMarkup.hashCode());
			result = result * 31 + (this.inputMessageContent == null ? 0 : this.inputMessageContent.hashCode());
			return result;
		}
	}

	/**
	 * Represents a link to a page containing an embedded video player or a
	 * video file.
	**/
	public static final class InputInlineQueryResultVideo extends InputInlineQueryResult {


		/**
		 * Unique identifier of the query result.
		**/
		public String id;

		/**
		 * Title of the result.
		**/
		public String title;

		/**
		 * A short description of the result, if known.
		**/
		public String description;

		/**
		 * The URL of the video thumbnail (JPEG), if it exists.
		**/
		public String thumbnailUrl;

		/**
		 * URL of the embedded video player or video file.
		**/
		public String videoUrl;

		/**
		 * MIME type of the content of the video URL, only &quot;text/html&quot; or &quot;video/mp4&quot; are currently supported.
		**/
		public String mimeType;

		/**
		 * Width of the video.
		**/
		public int videoWidth;

		/**
		 * Height of the video.
		**/
		public int videoHeight;

		/**
		 * Video duration, in seconds.
		**/
		public int videoDuration;

		/**
		 * The message reply markup; pass null if none. Must be of type replyMarkupInlineKeyboard or null.
		**/
		public ReplyMarkup replyMarkup;

		/**
		 * The content of the message to be sent. Must be one of the following types: inputMessageText, inputMessageVideo, inputMessageInvoice, inputMessageLocation, inputMessageVenue or inputMessageContact.
		**/
		public InputMessageContent inputMessageContent;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1724073191;

		/**
		 * Represents a link to a page containing an embedded video player or a video file.
		**/
		public InputInlineQueryResultVideo() {}

		/**
		 * Represents a link to a page containing an embedded video player or a video file.
		 *
		 * @param id Unique identifier of the query result.
		 * @param title Title of the result.
		 * @param description A short description of the result, if known.
		 * @param thumbnailUrl The URL of the video thumbnail (JPEG), if it exists.
		 * @param videoUrl URL of the embedded video player or video file.
		 * @param mimeType MIME type of the content of the video URL, only &quot;text/html&quot; or &quot;video/mp4&quot; are currently supported.
		 * @param videoWidth Width of the video.
		 * @param videoHeight Height of the video.
		 * @param videoDuration Video duration, in seconds.
		 * @param replyMarkup The message reply markup; pass null if none. Must be of type replyMarkupInlineKeyboard or null.
		 * @param inputMessageContent The content of the message to be sent. Must be one of the following types: inputMessageText, inputMessageVideo, inputMessageInvoice, inputMessageLocation, inputMessageVenue or inputMessageContact.
		**/
		public InputInlineQueryResultVideo(String id,
				String title,
				String description,
				String thumbnailUrl,
				String videoUrl,
				String mimeType,
				int videoWidth,
				int videoHeight,
				int videoDuration,
				ReplyMarkup replyMarkup,
				InputMessageContent inputMessageContent) {
			this.id = id;
			this.title = title;
			this.description = description;
			this.thumbnailUrl = thumbnailUrl;
			this.videoUrl = videoUrl;
			this.mimeType = mimeType;
			this.videoWidth = videoWidth;
			this.videoHeight = videoHeight;
			this.videoDuration = videoDuration;
			this.replyMarkup = replyMarkup;
			this.inputMessageContent = inputMessageContent;
		}

		/**
		 * Represents a link to a page containing an embedded video player or a video file.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputInlineQueryResultVideo(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] idTmp = new byte[input.readInt()];
				input.readFully(idTmp);
				this.id = new String(idTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] descriptionTmp = new byte[input.readInt()];
				input.readFully(descriptionTmp);
				this.description = new String(descriptionTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] thumbnailUrlTmp = new byte[input.readInt()];
				input.readFully(thumbnailUrlTmp);
				this.thumbnailUrl = new String(thumbnailUrlTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] videoUrlTmp = new byte[input.readInt()];
				input.readFully(videoUrlTmp);
				this.videoUrl = new String(videoUrlTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] mimeTypeTmp = new byte[input.readInt()];
				input.readFully(mimeTypeTmp);
				this.mimeType = new String(mimeTypeTmp, StandardCharsets.UTF_8);
			}
			this.videoWidth = input.readInt();
			this.videoHeight = input.readInt();
			this.videoDuration = input.readInt();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ReplyMarkupRemoveKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupRemoveKeyboard(input); break;
					case ReplyMarkupForceReply.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupForceReply(input); break;
					case ReplyMarkupShowKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupShowKeyboard(input); break;
					case ReplyMarkupInlineKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupInlineKeyboard(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputMessageText.CONSTRUCTOR: this.inputMessageContent = new InputMessageText(input); break;
					case InputMessageAnimation.CONSTRUCTOR: this.inputMessageContent = new InputMessageAnimation(input); break;
					case InputMessageAudio.CONSTRUCTOR: this.inputMessageContent = new InputMessageAudio(input); break;
					case InputMessageDocument.CONSTRUCTOR: this.inputMessageContent = new InputMessageDocument(input); break;
					case InputMessagePhoto.CONSTRUCTOR: this.inputMessageContent = new InputMessagePhoto(input); break;
					case InputMessageSticker.CONSTRUCTOR: this.inputMessageContent = new InputMessageSticker(input); break;
					case InputMessageVideo.CONSTRUCTOR: this.inputMessageContent = new InputMessageVideo(input); break;
					case InputMessageVideoNote.CONSTRUCTOR: this.inputMessageContent = new InputMessageVideoNote(input); break;
					case InputMessageVoiceNote.CONSTRUCTOR: this.inputMessageContent = new InputMessageVoiceNote(input); break;
					case InputMessageLocation.CONSTRUCTOR: this.inputMessageContent = new InputMessageLocation(input); break;
					case InputMessageVenue.CONSTRUCTOR: this.inputMessageContent = new InputMessageVenue(input); break;
					case InputMessageContact.CONSTRUCTOR: this.inputMessageContent = new InputMessageContact(input); break;
					case InputMessageDice.CONSTRUCTOR: this.inputMessageContent = new InputMessageDice(input); break;
					case InputMessageGame.CONSTRUCTOR: this.inputMessageContent = new InputMessageGame(input); break;
					case InputMessageInvoice.CONSTRUCTOR: this.inputMessageContent = new InputMessageInvoice(input); break;
					case InputMessagePoll.CONSTRUCTOR: this.inputMessageContent = new InputMessagePoll(input); break;
					case InputMessageForwarded.CONSTRUCTOR: this.inputMessageContent = new InputMessageForwarded(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputInlineQueryResultVideo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputInlineQueryResultVideo.CONSTRUCTOR);
			if (this.id == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] idTmp = this.id.getBytes(StandardCharsets.UTF_8);
				output.writeInt(idTmp.length);
				output.write(idTmp);
			}
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
			if (this.description == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] descriptionTmp = this.description.getBytes(StandardCharsets.UTF_8);
				output.writeInt(descriptionTmp.length);
				output.write(descriptionTmp);
			}
			if (this.thumbnailUrl == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] thumbnailUrlTmp = this.thumbnailUrl.getBytes(StandardCharsets.UTF_8);
				output.writeInt(thumbnailUrlTmp.length);
				output.write(thumbnailUrlTmp);
			}
			if (this.videoUrl == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] videoUrlTmp = this.videoUrl.getBytes(StandardCharsets.UTF_8);
				output.writeInt(videoUrlTmp.length);
				output.write(videoUrlTmp);
			}
			if (this.mimeType == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] mimeTypeTmp = this.mimeType.getBytes(StandardCharsets.UTF_8);
				output.writeInt(mimeTypeTmp.length);
				output.write(mimeTypeTmp);
			}
			output.writeInt(this.videoWidth);
			output.writeInt(this.videoHeight);
			output.writeInt(this.videoDuration);
			if (this.replyMarkup == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.replyMarkup.serialize(output);
			}
			if (this.inputMessageContent == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.inputMessageContent.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputInlineQueryResultVideo inputInlineQueryResultVideo = (InputInlineQueryResultVideo) o;
			if (this.id != inputInlineQueryResultVideo.id) {
				return false;
			}
			if (this.title != inputInlineQueryResultVideo.title) {
				return false;
			}
			if (this.description != inputInlineQueryResultVideo.description) {
				return false;
			}
			if (this.thumbnailUrl != inputInlineQueryResultVideo.thumbnailUrl) {
				return false;
			}
			if (this.videoUrl != inputInlineQueryResultVideo.videoUrl) {
				return false;
			}
			if (this.mimeType != inputInlineQueryResultVideo.mimeType) {
				return false;
			}
			if (this.videoWidth != inputInlineQueryResultVideo.videoWidth) {
				return false;
			}
			if (this.videoHeight != inputInlineQueryResultVideo.videoHeight) {
				return false;
			}
			if (this.videoDuration != inputInlineQueryResultVideo.videoDuration) {
				return false;
			}
			if (!Objects.equals(this.replyMarkup, inputInlineQueryResultVideo.replyMarkup)) {
				return false;
			}
			if (!Objects.equals(this.inputMessageContent, inputInlineQueryResultVideo.inputMessageContent)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.videoWidth);
			result = result * 31 + (this.id == null ? 0 : this.id.hashCode());
			result = result * 31 + (this.title == null ? 0 : this.title.hashCode());
			result = result * 31 + (this.description == null ? 0 : this.description.hashCode());
			result = result * 31 + (this.thumbnailUrl == null ? 0 : this.thumbnailUrl.hashCode());
			result = result * 31 + (this.videoUrl == null ? 0 : this.videoUrl.hashCode());
			result = result * 31 + (this.mimeType == null ? 0 : this.mimeType.hashCode());
			result = result * 31 + (this.replyMarkup == null ? 0 : this.replyMarkup.hashCode());
			result = result * 31 + (this.inputMessageContent == null ? 0 : this.inputMessageContent.hashCode());
			return result;
		}
	}

	/**
	 * Represents a link to an opus-encoded audio file within an OGG
	 * container, single channel audio.
	**/
	public static final class InputInlineQueryResultVoiceNote extends InputInlineQueryResult {


		/**
		 * Unique identifier of the query result.
		**/
		public String id;

		/**
		 * Title of the voice note.
		**/
		public String title;

		/**
		 * The URL of the voice note file.
		**/
		public String voiceNoteUrl;

		/**
		 * Duration of the voice note, in seconds.
		**/
		public int voiceNoteDuration;

		/**
		 * The message reply markup; pass null if none. Must be of type replyMarkupInlineKeyboard or null.
		**/
		public ReplyMarkup replyMarkup;

		/**
		 * The content of the message to be sent. Must be one of the following types: inputMessageText, inputMessageVoiceNote, inputMessageInvoice, inputMessageLocation, inputMessageVenue or inputMessageContact.
		**/
		public InputMessageContent inputMessageContent;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1790072503;

		/**
		 * Represents a link to an opus-encoded audio file within an OGG container, single channel audio.
		**/
		public InputInlineQueryResultVoiceNote() {}

		/**
		 * Represents a link to an opus-encoded audio file within an OGG container, single channel audio.
		 *
		 * @param id Unique identifier of the query result.
		 * @param title Title of the voice note.
		 * @param voiceNoteUrl The URL of the voice note file.
		 * @param voiceNoteDuration Duration of the voice note, in seconds.
		 * @param replyMarkup The message reply markup; pass null if none. Must be of type replyMarkupInlineKeyboard or null.
		 * @param inputMessageContent The content of the message to be sent. Must be one of the following types: inputMessageText, inputMessageVoiceNote, inputMessageInvoice, inputMessageLocation, inputMessageVenue or inputMessageContact.
		**/
		public InputInlineQueryResultVoiceNote(String id,
				String title,
				String voiceNoteUrl,
				int voiceNoteDuration,
				ReplyMarkup replyMarkup,
				InputMessageContent inputMessageContent) {
			this.id = id;
			this.title = title;
			this.voiceNoteUrl = voiceNoteUrl;
			this.voiceNoteDuration = voiceNoteDuration;
			this.replyMarkup = replyMarkup;
			this.inputMessageContent = inputMessageContent;
		}

		/**
		 * Represents a link to an opus-encoded audio file within an OGG container, single channel audio.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputInlineQueryResultVoiceNote(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] idTmp = new byte[input.readInt()];
				input.readFully(idTmp);
				this.id = new String(idTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] voiceNoteUrlTmp = new byte[input.readInt()];
				input.readFully(voiceNoteUrlTmp);
				this.voiceNoteUrl = new String(voiceNoteUrlTmp, StandardCharsets.UTF_8);
			}
			this.voiceNoteDuration = input.readInt();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ReplyMarkupRemoveKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupRemoveKeyboard(input); break;
					case ReplyMarkupForceReply.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupForceReply(input); break;
					case ReplyMarkupShowKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupShowKeyboard(input); break;
					case ReplyMarkupInlineKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupInlineKeyboard(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputMessageText.CONSTRUCTOR: this.inputMessageContent = new InputMessageText(input); break;
					case InputMessageAnimation.CONSTRUCTOR: this.inputMessageContent = new InputMessageAnimation(input); break;
					case InputMessageAudio.CONSTRUCTOR: this.inputMessageContent = new InputMessageAudio(input); break;
					case InputMessageDocument.CONSTRUCTOR: this.inputMessageContent = new InputMessageDocument(input); break;
					case InputMessagePhoto.CONSTRUCTOR: this.inputMessageContent = new InputMessagePhoto(input); break;
					case InputMessageSticker.CONSTRUCTOR: this.inputMessageContent = new InputMessageSticker(input); break;
					case InputMessageVideo.CONSTRUCTOR: this.inputMessageContent = new InputMessageVideo(input); break;
					case InputMessageVideoNote.CONSTRUCTOR: this.inputMessageContent = new InputMessageVideoNote(input); break;
					case InputMessageVoiceNote.CONSTRUCTOR: this.inputMessageContent = new InputMessageVoiceNote(input); break;
					case InputMessageLocation.CONSTRUCTOR: this.inputMessageContent = new InputMessageLocation(input); break;
					case InputMessageVenue.CONSTRUCTOR: this.inputMessageContent = new InputMessageVenue(input); break;
					case InputMessageContact.CONSTRUCTOR: this.inputMessageContent = new InputMessageContact(input); break;
					case InputMessageDice.CONSTRUCTOR: this.inputMessageContent = new InputMessageDice(input); break;
					case InputMessageGame.CONSTRUCTOR: this.inputMessageContent = new InputMessageGame(input); break;
					case InputMessageInvoice.CONSTRUCTOR: this.inputMessageContent = new InputMessageInvoice(input); break;
					case InputMessagePoll.CONSTRUCTOR: this.inputMessageContent = new InputMessagePoll(input); break;
					case InputMessageForwarded.CONSTRUCTOR: this.inputMessageContent = new InputMessageForwarded(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputInlineQueryResultVoiceNote.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputInlineQueryResultVoiceNote.CONSTRUCTOR);
			if (this.id == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] idTmp = this.id.getBytes(StandardCharsets.UTF_8);
				output.writeInt(idTmp.length);
				output.write(idTmp);
			}
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
			if (this.voiceNoteUrl == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] voiceNoteUrlTmp = this.voiceNoteUrl.getBytes(StandardCharsets.UTF_8);
				output.writeInt(voiceNoteUrlTmp.length);
				output.write(voiceNoteUrlTmp);
			}
			output.writeInt(this.voiceNoteDuration);
			if (this.replyMarkup == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.replyMarkup.serialize(output);
			}
			if (this.inputMessageContent == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.inputMessageContent.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputInlineQueryResultVoiceNote inputInlineQueryResultVoiceNote = (InputInlineQueryResultVoiceNote) o;
			if (this.id != inputInlineQueryResultVoiceNote.id) {
				return false;
			}
			if (this.title != inputInlineQueryResultVoiceNote.title) {
				return false;
			}
			if (this.voiceNoteUrl != inputInlineQueryResultVoiceNote.voiceNoteUrl) {
				return false;
			}
			if (this.voiceNoteDuration != inputInlineQueryResultVoiceNote.voiceNoteDuration) {
				return false;
			}
			if (!Objects.equals(this.replyMarkup, inputInlineQueryResultVoiceNote.replyMarkup)) {
				return false;
			}
			if (!Objects.equals(this.inputMessageContent, inputInlineQueryResultVoiceNote.inputMessageContent)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.voiceNoteDuration);
			result = result * 31 + (this.id == null ? 0 : this.id.hashCode());
			result = result * 31 + (this.title == null ? 0 : this.title.hashCode());
			result = result * 31 + (this.voiceNoteUrl == null ? 0 : this.voiceNoteUrl.hashCode());
			result = result * 31 + (this.replyMarkup == null ? 0 : this.replyMarkup.hashCode());
			result = result * 31 + (this.inputMessageContent == null ? 0 : this.inputMessageContent.hashCode());
			return result;
		}
	}

	/**
	 * An invoice from a message of the type messageInvoice.
	**/
	public static final class InputInvoiceMessage extends InputInvoice {


		/**
		 * Chat identifier of the message.
		**/
		public long chatId;

		/**
		 * Message identifier.
		**/
		public long messageId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1490872848;

		/**
		 * An invoice from a message of the type messageInvoice.
		**/
		public InputInvoiceMessage() {}

		/**
		 * An invoice from a message of the type messageInvoice.
		 *
		 * @param chatId Chat identifier of the message.
		 * @param messageId Message identifier.
		**/
		public InputInvoiceMessage(long chatId, long messageId) {
			this.chatId = chatId;
			this.messageId = messageId;
		}

		/**
		 * An invoice from a message of the type messageInvoice.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputInvoiceMessage(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputInvoiceMessage.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputInvoiceMessage.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputInvoiceMessage inputInvoiceMessage = (InputInvoiceMessage) o;
			if (this.chatId != inputInvoiceMessage.chatId) {
				return false;
			}
			if (this.messageId != inputInvoiceMessage.messageId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * An invoice from a link of the type internalLinkTypeInvoice.
	**/
	public static final class InputInvoiceName extends InputInvoice {


		/**
		 * Name of the invoice.
		**/
		public String name;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1312155917;

		/**
		 * An invoice from a link of the type internalLinkTypeInvoice.
		**/
		public InputInvoiceName() {}

		/**
		 * An invoice from a link of the type internalLinkTypeInvoice.
		 *
		 * @param name Name of the invoice.
		**/
		public InputInvoiceName(String name) {
			this.name = name;
		}

		/**
		 * An invoice from a link of the type internalLinkTypeInvoice.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputInvoiceName(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] nameTmp = new byte[input.readInt()];
				input.readFully(nameTmp);
				this.name = new String(nameTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputInvoiceName.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputInvoiceName.CONSTRUCTOR);
			if (this.name == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nameTmp = this.name.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nameTmp.length);
				output.write(nameTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputInvoiceName inputInvoiceName = (InputInvoiceName) o;
			if (this.name != inputInvoiceName.name) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.name == null ? 0 : this.name.hashCode();
		}
	}

	/**
	 * A text message.
	**/
	public static final class InputMessageText extends InputMessageContent {


		/**
		 * Formatted text to be sent; 1-getOption(&quot;message_text_length_max&quot;) characters. Only Bold, Italic, Underline, Strikethrough, Spoiler, CustomEmoji, Code, Pre, PreCode, TextUrl and MentionName entities are allowed to be specified manually.
		**/
		public FormattedText text;

		/**
		 * True, if rich web page previews for URLs in the message text must be disabled.
		**/
		public boolean disableWebPagePreview;

		/**
		 * True, if a chat message draft must be deleted.
		**/
		public boolean clearDraft;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 247050392;

		/**
		 * A text message.
		**/
		public InputMessageText() {}

		/**
		 * A text message.
		 *
		 * @param text Formatted text to be sent; 1-getOption(&quot;message_text_length_max&quot;) characters. Only Bold, Italic, Underline, Strikethrough, Spoiler, CustomEmoji, Code, Pre, PreCode, TextUrl and MentionName entities are allowed to be specified manually.
		 * @param disableWebPagePreview True, if rich web page previews for URLs in the message text must be disabled.
		 * @param clearDraft True, if a chat message draft must be deleted.
		**/
		public InputMessageText(FormattedText text,
				boolean disableWebPagePreview,
				boolean clearDraft) {
			this.text = text;
			this.disableWebPagePreview = disableWebPagePreview;
			this.clearDraft = clearDraft;
		}

		/**
		 * A text message.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputMessageText(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (FormattedText.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.text = new FormattedText(input);
			}
			this.disableWebPagePreview = input.readBoolean();
			this.clearDraft = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputMessageText.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputMessageText.CONSTRUCTOR);
			if (this.text == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.text.serialize(output);
			}
			output.writeBoolean(this.disableWebPagePreview);
			output.writeBoolean(this.clearDraft);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputMessageText inputMessageText = (InputMessageText) o;
			if (!Objects.equals(this.text, inputMessageText.text)) {
				return false;
			}
			if (this.disableWebPagePreview != inputMessageText.disableWebPagePreview) {
				return false;
			}
			if (this.clearDraft != inputMessageText.clearDraft) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.disableWebPagePreview);
			result = result * 31 + (this.text == null ? 0 : this.text.hashCode());
			return result;
		}
	}

	/**
	 * An animation message (GIF-style).
	**/
	public static final class InputMessageAnimation extends InputMessageContent {


		/**
		 * Animation file to be sent.
		**/
		public InputFile animation;

		/**
		 * Animation thumbnail; pass null to skip thumbnail uploading.
		**/
		public InputThumbnail thumbnail;

		/**
		 * File identifiers of the stickers added to the animation, if applicable.
		**/
		public int[] addedStickerFileIds;

		/**
		 * Duration of the animation, in seconds.
		**/
		public int duration;

		/**
		 * Width of the animation; may be replaced by the server.
		**/
		public int width;

		/**
		 * Height of the animation; may be replaced by the server.
		**/
		public int height;

		/**
		 * Animation caption; pass null to use an empty caption; 0-getOption(&quot;message_caption_length_max&quot;) characters.
		**/
		public FormattedText caption;

		/**
		 * True, if the animation preview must be covered by a spoiler animation; not supported in secret chats.
		**/
		public boolean hasSpoiler;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 850750601;

		/**
		 * An animation message (GIF-style).
		**/
		public InputMessageAnimation() {}

		/**
		 * An animation message (GIF-style).
		 *
		 * @param animation Animation file to be sent.
		 * @param thumbnail Animation thumbnail; pass null to skip thumbnail uploading.
		 * @param addedStickerFileIds File identifiers of the stickers added to the animation, if applicable.
		 * @param duration Duration of the animation, in seconds.
		 * @param width Width of the animation; may be replaced by the server.
		 * @param height Height of the animation; may be replaced by the server.
		 * @param caption Animation caption; pass null to use an empty caption; 0-getOption(&quot;message_caption_length_max&quot;) characters.
		 * @param hasSpoiler True, if the animation preview must be covered by a spoiler animation; not supported in secret chats.
		**/
		public InputMessageAnimation(InputFile animation,
				InputThumbnail thumbnail,
				int[] addedStickerFileIds,
				int duration,
				int width,
				int height,
				FormattedText caption,
				boolean hasSpoiler) {
			this.animation = animation;
			this.thumbnail = thumbnail;
			this.addedStickerFileIds = addedStickerFileIds;
			this.duration = duration;
			this.width = width;
			this.height = height;
			this.caption = caption;
			this.hasSpoiler = hasSpoiler;
		}

		/**
		 * An animation message (GIF-style).
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputMessageAnimation(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputFileId.CONSTRUCTOR: this.animation = new InputFileId(input); break;
					case InputFileRemote.CONSTRUCTOR: this.animation = new InputFileRemote(input); break;
					case InputFileLocal.CONSTRUCTOR: this.animation = new InputFileLocal(input); break;
					case InputFileGenerated.CONSTRUCTOR: this.animation = new InputFileGenerated(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				if (InputThumbnail.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.thumbnail = new InputThumbnail(input);
			}
			if (input.readBoolean()) {
				this.addedStickerFileIds = new int[input.readInt()];
				for (int i = 0; i < this.addedStickerFileIds.length; i++) {
					this.addedStickerFileIds[i] = input.readInt();
				}
			}
			this.duration = input.readInt();
			this.width = input.readInt();
			this.height = input.readInt();
			if (input.readBoolean()) {
				if (FormattedText.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.caption = new FormattedText(input);
			}
			this.hasSpoiler = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputMessageAnimation.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputMessageAnimation.CONSTRUCTOR);
			if (this.animation == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.animation.serialize(output);
			}
			if (this.thumbnail == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.thumbnail.serialize(output);
			}
			if (this.addedStickerFileIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.addedStickerFileIds.length);
				for (int i = 0; i < this.addedStickerFileIds.length; i++) {
					output.writeInt(this.addedStickerFileIds[i]);
				}
			}
			output.writeInt(this.duration);
			output.writeInt(this.width);
			output.writeInt(this.height);
			if (this.caption == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.caption.serialize(output);
			}
			output.writeBoolean(this.hasSpoiler);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputMessageAnimation inputMessageAnimation = (InputMessageAnimation) o;
			if (!Objects.equals(this.animation, inputMessageAnimation.animation)) {
				return false;
			}
			if (!Objects.equals(this.thumbnail, inputMessageAnimation.thumbnail)) {
				return false;
			}
			if (!Arrays.equals(this.addedStickerFileIds, inputMessageAnimation.addedStickerFileIds)) {
				return false;
			}
			if (this.duration != inputMessageAnimation.duration) {
				return false;
			}
			if (this.width != inputMessageAnimation.width) {
				return false;
			}
			if (this.height != inputMessageAnimation.height) {
				return false;
			}
			if (!Objects.equals(this.caption, inputMessageAnimation.caption)) {
				return false;
			}
			if (this.hasSpoiler != inputMessageAnimation.hasSpoiler) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.duration);
			result = result * 31 + (this.animation == null ? 0 : this.animation.hashCode());
			result = result * 31 + (this.thumbnail == null ? 0 : this.thumbnail.hashCode());
			result = result * 31 + (Arrays.hashCode(this.addedStickerFileIds));
			result = result * 31 + (this.caption == null ? 0 : this.caption.hashCode());
			return result;
		}
	}

	/**
	 * An audio message.
	**/
	public static final class InputMessageAudio extends InputMessageContent {


		/**
		 * Audio file to be sent.
		**/
		public InputFile audio;

		/**
		 * Thumbnail of the cover for the album; pass null to skip thumbnail uploading.
		**/
		public InputThumbnail albumCoverThumbnail;

		/**
		 * Duration of the audio, in seconds; may be replaced by the server.
		**/
		public int duration;

		/**
		 * Title of the audio; 0-64 characters; may be replaced by the server.
		**/
		public String title;

		/**
		 * Performer of the audio; 0-64 characters, may be replaced by the server.
		**/
		public String performer;

		/**
		 * Audio caption; pass null to use an empty caption; 0-getOption(&quot;message_caption_length_max&quot;) characters.
		**/
		public FormattedText caption;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -626786126;

		/**
		 * An audio message.
		**/
		public InputMessageAudio() {}

		/**
		 * An audio message.
		 *
		 * @param audio Audio file to be sent.
		 * @param albumCoverThumbnail Thumbnail of the cover for the album; pass null to skip thumbnail uploading.
		 * @param duration Duration of the audio, in seconds; may be replaced by the server.
		 * @param title Title of the audio; 0-64 characters; may be replaced by the server.
		 * @param performer Performer of the audio; 0-64 characters, may be replaced by the server.
		 * @param caption Audio caption; pass null to use an empty caption; 0-getOption(&quot;message_caption_length_max&quot;) characters.
		**/
		public InputMessageAudio(InputFile audio,
				InputThumbnail albumCoverThumbnail,
				int duration,
				String title,
				String performer,
				FormattedText caption) {
			this.audio = audio;
			this.albumCoverThumbnail = albumCoverThumbnail;
			this.duration = duration;
			this.title = title;
			this.performer = performer;
			this.caption = caption;
		}

		/**
		 * An audio message.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputMessageAudio(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputFileId.CONSTRUCTOR: this.audio = new InputFileId(input); break;
					case InputFileRemote.CONSTRUCTOR: this.audio = new InputFileRemote(input); break;
					case InputFileLocal.CONSTRUCTOR: this.audio = new InputFileLocal(input); break;
					case InputFileGenerated.CONSTRUCTOR: this.audio = new InputFileGenerated(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				if (InputThumbnail.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.albumCoverThumbnail = new InputThumbnail(input);
			}
			this.duration = input.readInt();
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] performerTmp = new byte[input.readInt()];
				input.readFully(performerTmp);
				this.performer = new String(performerTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (FormattedText.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.caption = new FormattedText(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputMessageAudio.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputMessageAudio.CONSTRUCTOR);
			if (this.audio == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.audio.serialize(output);
			}
			if (this.albumCoverThumbnail == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.albumCoverThumbnail.serialize(output);
			}
			output.writeInt(this.duration);
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
			if (this.performer == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] performerTmp = this.performer.getBytes(StandardCharsets.UTF_8);
				output.writeInt(performerTmp.length);
				output.write(performerTmp);
			}
			if (this.caption == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.caption.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputMessageAudio inputMessageAudio = (InputMessageAudio) o;
			if (!Objects.equals(this.audio, inputMessageAudio.audio)) {
				return false;
			}
			if (!Objects.equals(this.albumCoverThumbnail, inputMessageAudio.albumCoverThumbnail)) {
				return false;
			}
			if (this.duration != inputMessageAudio.duration) {
				return false;
			}
			if (this.title != inputMessageAudio.title) {
				return false;
			}
			if (this.performer != inputMessageAudio.performer) {
				return false;
			}
			if (!Objects.equals(this.caption, inputMessageAudio.caption)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.duration);
			result = result * 31 + (this.audio == null ? 0 : this.audio.hashCode());
			result = result * 31 + (this.albumCoverThumbnail == null ? 0 : this.albumCoverThumbnail.hashCode());
			result = result * 31 + (this.title == null ? 0 : this.title.hashCode());
			result = result * 31 + (this.performer == null ? 0 : this.performer.hashCode());
			result = result * 31 + (this.caption == null ? 0 : this.caption.hashCode());
			return result;
		}
	}

	/**
	 * A document message (general file).
	**/
	public static final class InputMessageDocument extends InputMessageContent {


		/**
		 * Document to be sent.
		**/
		public InputFile document;

		/**
		 * Document thumbnail; pass null to skip thumbnail uploading.
		**/
		public InputThumbnail thumbnail;

		/**
		 * If true, automatic file type detection will be disabled and the document will always be sent as file. Always true for files sent to secret chats.
		**/
		public boolean disableContentTypeDetection;

		/**
		 * Document caption; pass null to use an empty caption; 0-getOption(&quot;message_caption_length_max&quot;) characters.
		**/
		public FormattedText caption;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1633383097;

		/**
		 * A document message (general file).
		**/
		public InputMessageDocument() {}

		/**
		 * A document message (general file).
		 *
		 * @param document Document to be sent.
		 * @param thumbnail Document thumbnail; pass null to skip thumbnail uploading.
		 * @param disableContentTypeDetection If true, automatic file type detection will be disabled and the document will always be sent as file. Always true for files sent to secret chats.
		 * @param caption Document caption; pass null to use an empty caption; 0-getOption(&quot;message_caption_length_max&quot;) characters.
		**/
		public InputMessageDocument(InputFile document,
				InputThumbnail thumbnail,
				boolean disableContentTypeDetection,
				FormattedText caption) {
			this.document = document;
			this.thumbnail = thumbnail;
			this.disableContentTypeDetection = disableContentTypeDetection;
			this.caption = caption;
		}

		/**
		 * A document message (general file).
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputMessageDocument(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputFileId.CONSTRUCTOR: this.document = new InputFileId(input); break;
					case InputFileRemote.CONSTRUCTOR: this.document = new InputFileRemote(input); break;
					case InputFileLocal.CONSTRUCTOR: this.document = new InputFileLocal(input); break;
					case InputFileGenerated.CONSTRUCTOR: this.document = new InputFileGenerated(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				if (InputThumbnail.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.thumbnail = new InputThumbnail(input);
			}
			this.disableContentTypeDetection = input.readBoolean();
			if (input.readBoolean()) {
				if (FormattedText.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.caption = new FormattedText(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputMessageDocument.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputMessageDocument.CONSTRUCTOR);
			if (this.document == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.document.serialize(output);
			}
			if (this.thumbnail == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.thumbnail.serialize(output);
			}
			output.writeBoolean(this.disableContentTypeDetection);
			if (this.caption == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.caption.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputMessageDocument inputMessageDocument = (InputMessageDocument) o;
			if (!Objects.equals(this.document, inputMessageDocument.document)) {
				return false;
			}
			if (!Objects.equals(this.thumbnail, inputMessageDocument.thumbnail)) {
				return false;
			}
			if (this.disableContentTypeDetection != inputMessageDocument.disableContentTypeDetection) {
				return false;
			}
			if (!Objects.equals(this.caption, inputMessageDocument.caption)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.disableContentTypeDetection);
			result = result * 31 + (this.document == null ? 0 : this.document.hashCode());
			result = result * 31 + (this.thumbnail == null ? 0 : this.thumbnail.hashCode());
			result = result * 31 + (this.caption == null ? 0 : this.caption.hashCode());
			return result;
		}
	}

	/**
	 * A photo message.
	**/
	public static final class InputMessagePhoto extends InputMessageContent {


		/**
		 * Photo to send. The photo must be at most 10 MB in size. The photo&#039;s width and height must not exceed 10000 in total. Width and height ratio must be at most 20.
		**/
		public InputFile photo;

		/**
		 * Photo thumbnail to be sent; pass null to skip thumbnail uploading. The thumbnail is sent to the other party only in secret chats.
		**/
		public InputThumbnail thumbnail;

		/**
		 * File identifiers of the stickers added to the photo, if applicable.
		**/
		public int[] addedStickerFileIds;

		/**
		 * Photo width.
		**/
		public int width;

		/**
		 * Photo height.
		**/
		public int height;

		/**
		 * Photo caption; pass null to use an empty caption; 0-getOption(&quot;message_caption_length_max&quot;) characters.
		**/
		public FormattedText caption;

		/**
		 * Photo self-destruct time, in seconds (0-60). A non-zero self-destruct time can be specified only in private chats.
		**/
		public int selfDestructTime;

		/**
		 * True, if the photo preview must be covered by a spoiler animation; not supported in secret chats.
		**/
		public boolean hasSpoiler;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1658132071;

		/**
		 * A photo message.
		**/
		public InputMessagePhoto() {}

		/**
		 * A photo message.
		 *
		 * @param photo Photo to send. The photo must be at most 10 MB in size. The photo&#039;s width and height must not exceed 10000 in total. Width and height ratio must be at most 20.
		 * @param thumbnail Photo thumbnail to be sent; pass null to skip thumbnail uploading. The thumbnail is sent to the other party only in secret chats.
		 * @param addedStickerFileIds File identifiers of the stickers added to the photo, if applicable.
		 * @param width Photo width.
		 * @param height Photo height.
		 * @param caption Photo caption; pass null to use an empty caption; 0-getOption(&quot;message_caption_length_max&quot;) characters.
		 * @param selfDestructTime Photo self-destruct time, in seconds (0-60). A non-zero self-destruct time can be specified only in private chats.
		 * @param hasSpoiler True, if the photo preview must be covered by a spoiler animation; not supported in secret chats.
		**/
		public InputMessagePhoto(InputFile photo,
				InputThumbnail thumbnail,
				int[] addedStickerFileIds,
				int width,
				int height,
				FormattedText caption,
				int selfDestructTime,
				boolean hasSpoiler) {
			this.photo = photo;
			this.thumbnail = thumbnail;
			this.addedStickerFileIds = addedStickerFileIds;
			this.width = width;
			this.height = height;
			this.caption = caption;
			this.selfDestructTime = selfDestructTime;
			this.hasSpoiler = hasSpoiler;
		}

		/**
		 * A photo message.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputMessagePhoto(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputFileId.CONSTRUCTOR: this.photo = new InputFileId(input); break;
					case InputFileRemote.CONSTRUCTOR: this.photo = new InputFileRemote(input); break;
					case InputFileLocal.CONSTRUCTOR: this.photo = new InputFileLocal(input); break;
					case InputFileGenerated.CONSTRUCTOR: this.photo = new InputFileGenerated(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				if (InputThumbnail.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.thumbnail = new InputThumbnail(input);
			}
			if (input.readBoolean()) {
				this.addedStickerFileIds = new int[input.readInt()];
				for (int i = 0; i < this.addedStickerFileIds.length; i++) {
					this.addedStickerFileIds[i] = input.readInt();
				}
			}
			this.width = input.readInt();
			this.height = input.readInt();
			if (input.readBoolean()) {
				if (FormattedText.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.caption = new FormattedText(input);
			}
			this.selfDestructTime = input.readInt();
			this.hasSpoiler = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputMessagePhoto.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputMessagePhoto.CONSTRUCTOR);
			if (this.photo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.photo.serialize(output);
			}
			if (this.thumbnail == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.thumbnail.serialize(output);
			}
			if (this.addedStickerFileIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.addedStickerFileIds.length);
				for (int i = 0; i < this.addedStickerFileIds.length; i++) {
					output.writeInt(this.addedStickerFileIds[i]);
				}
			}
			output.writeInt(this.width);
			output.writeInt(this.height);
			if (this.caption == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.caption.serialize(output);
			}
			output.writeInt(this.selfDestructTime);
			output.writeBoolean(this.hasSpoiler);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputMessagePhoto inputMessagePhoto = (InputMessagePhoto) o;
			if (!Objects.equals(this.photo, inputMessagePhoto.photo)) {
				return false;
			}
			if (!Objects.equals(this.thumbnail, inputMessagePhoto.thumbnail)) {
				return false;
			}
			if (!Arrays.equals(this.addedStickerFileIds, inputMessagePhoto.addedStickerFileIds)) {
				return false;
			}
			if (this.width != inputMessagePhoto.width) {
				return false;
			}
			if (this.height != inputMessagePhoto.height) {
				return false;
			}
			if (!Objects.equals(this.caption, inputMessagePhoto.caption)) {
				return false;
			}
			if (this.selfDestructTime != inputMessagePhoto.selfDestructTime) {
				return false;
			}
			if (this.hasSpoiler != inputMessagePhoto.hasSpoiler) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.width);
			result = result * 31 + (this.photo == null ? 0 : this.photo.hashCode());
			result = result * 31 + (this.thumbnail == null ? 0 : this.thumbnail.hashCode());
			result = result * 31 + (Arrays.hashCode(this.addedStickerFileIds));
			result = result * 31 + (this.caption == null ? 0 : this.caption.hashCode());
			return result;
		}
	}

	/**
	 * A sticker message.
	**/
	public static final class InputMessageSticker extends InputMessageContent {


		/**
		 * Sticker to be sent.
		**/
		public InputFile sticker;

		/**
		 * Sticker thumbnail; pass null to skip thumbnail uploading.
		**/
		public InputThumbnail thumbnail;

		/**
		 * Sticker width.
		**/
		public int width;

		/**
		 * Sticker height.
		**/
		public int height;

		/**
		 * Emoji used to choose the sticker.
		**/
		public String emoji;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1072805625;

		/**
		 * A sticker message.
		**/
		public InputMessageSticker() {}

		/**
		 * A sticker message.
		 *
		 * @param sticker Sticker to be sent.
		 * @param thumbnail Sticker thumbnail; pass null to skip thumbnail uploading.
		 * @param width Sticker width.
		 * @param height Sticker height.
		 * @param emoji Emoji used to choose the sticker.
		**/
		public InputMessageSticker(InputFile sticker,
				InputThumbnail thumbnail,
				int width,
				int height,
				String emoji) {
			this.sticker = sticker;
			this.thumbnail = thumbnail;
			this.width = width;
			this.height = height;
			this.emoji = emoji;
		}

		/**
		 * A sticker message.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputMessageSticker(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputFileId.CONSTRUCTOR: this.sticker = new InputFileId(input); break;
					case InputFileRemote.CONSTRUCTOR: this.sticker = new InputFileRemote(input); break;
					case InputFileLocal.CONSTRUCTOR: this.sticker = new InputFileLocal(input); break;
					case InputFileGenerated.CONSTRUCTOR: this.sticker = new InputFileGenerated(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				if (InputThumbnail.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.thumbnail = new InputThumbnail(input);
			}
			this.width = input.readInt();
			this.height = input.readInt();
			if (input.readBoolean()) {
				byte[] emojiTmp = new byte[input.readInt()];
				input.readFully(emojiTmp);
				this.emoji = new String(emojiTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputMessageSticker.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputMessageSticker.CONSTRUCTOR);
			if (this.sticker == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.sticker.serialize(output);
			}
			if (this.thumbnail == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.thumbnail.serialize(output);
			}
			output.writeInt(this.width);
			output.writeInt(this.height);
			if (this.emoji == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] emojiTmp = this.emoji.getBytes(StandardCharsets.UTF_8);
				output.writeInt(emojiTmp.length);
				output.write(emojiTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputMessageSticker inputMessageSticker = (InputMessageSticker) o;
			if (!Objects.equals(this.sticker, inputMessageSticker.sticker)) {
				return false;
			}
			if (!Objects.equals(this.thumbnail, inputMessageSticker.thumbnail)) {
				return false;
			}
			if (this.width != inputMessageSticker.width) {
				return false;
			}
			if (this.height != inputMessageSticker.height) {
				return false;
			}
			if (this.emoji != inputMessageSticker.emoji) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.width);
			result = result * 31 + (this.sticker == null ? 0 : this.sticker.hashCode());
			result = result * 31 + (this.thumbnail == null ? 0 : this.thumbnail.hashCode());
			result = result * 31 + (this.emoji == null ? 0 : this.emoji.hashCode());
			return result;
		}
	}

	/**
	 * A video message.
	**/
	public static final class InputMessageVideo extends InputMessageContent {


		/**
		 * Video to be sent.
		**/
		public InputFile video;

		/**
		 * Video thumbnail; pass null to skip thumbnail uploading.
		**/
		public InputThumbnail thumbnail;

		/**
		 * File identifiers of the stickers added to the video, if applicable.
		**/
		public int[] addedStickerFileIds;

		/**
		 * Duration of the video, in seconds.
		**/
		public int duration;

		/**
		 * Video width.
		**/
		public int width;

		/**
		 * Video height.
		**/
		public int height;

		/**
		 * True, if the video is supposed to be streamed.
		**/
		public boolean supportsStreaming;

		/**
		 * Video caption; pass null to use an empty caption; 0-getOption(&quot;message_caption_length_max&quot;) characters.
		**/
		public FormattedText caption;

		/**
		 * Video self-destruct time, in seconds (0-60). A non-zero self-destruct time can be specified only in private chats.
		**/
		public int selfDestructTime;

		/**
		 * True, if the video preview must be covered by a spoiler animation; not supported in secret chats.
		**/
		public boolean hasSpoiler;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1699308024;

		/**
		 * A video message.
		**/
		public InputMessageVideo() {}

		/**
		 * A video message.
		 *
		 * @param video Video to be sent.
		 * @param thumbnail Video thumbnail; pass null to skip thumbnail uploading.
		 * @param addedStickerFileIds File identifiers of the stickers added to the video, if applicable.
		 * @param duration Duration of the video, in seconds.
		 * @param width Video width.
		 * @param height Video height.
		 * @param supportsStreaming True, if the video is supposed to be streamed.
		 * @param caption Video caption; pass null to use an empty caption; 0-getOption(&quot;message_caption_length_max&quot;) characters.
		 * @param selfDestructTime Video self-destruct time, in seconds (0-60). A non-zero self-destruct time can be specified only in private chats.
		 * @param hasSpoiler True, if the video preview must be covered by a spoiler animation; not supported in secret chats.
		**/
		public InputMessageVideo(InputFile video,
				InputThumbnail thumbnail,
				int[] addedStickerFileIds,
				int duration,
				int width,
				int height,
				boolean supportsStreaming,
				FormattedText caption,
				int selfDestructTime,
				boolean hasSpoiler) {
			this.video = video;
			this.thumbnail = thumbnail;
			this.addedStickerFileIds = addedStickerFileIds;
			this.duration = duration;
			this.width = width;
			this.height = height;
			this.supportsStreaming = supportsStreaming;
			this.caption = caption;
			this.selfDestructTime = selfDestructTime;
			this.hasSpoiler = hasSpoiler;
		}

		/**
		 * A video message.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputMessageVideo(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputFileId.CONSTRUCTOR: this.video = new InputFileId(input); break;
					case InputFileRemote.CONSTRUCTOR: this.video = new InputFileRemote(input); break;
					case InputFileLocal.CONSTRUCTOR: this.video = new InputFileLocal(input); break;
					case InputFileGenerated.CONSTRUCTOR: this.video = new InputFileGenerated(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				if (InputThumbnail.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.thumbnail = new InputThumbnail(input);
			}
			if (input.readBoolean()) {
				this.addedStickerFileIds = new int[input.readInt()];
				for (int i = 0; i < this.addedStickerFileIds.length; i++) {
					this.addedStickerFileIds[i] = input.readInt();
				}
			}
			this.duration = input.readInt();
			this.width = input.readInt();
			this.height = input.readInt();
			this.supportsStreaming = input.readBoolean();
			if (input.readBoolean()) {
				if (FormattedText.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.caption = new FormattedText(input);
			}
			this.selfDestructTime = input.readInt();
			this.hasSpoiler = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputMessageVideo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputMessageVideo.CONSTRUCTOR);
			if (this.video == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.video.serialize(output);
			}
			if (this.thumbnail == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.thumbnail.serialize(output);
			}
			if (this.addedStickerFileIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.addedStickerFileIds.length);
				for (int i = 0; i < this.addedStickerFileIds.length; i++) {
					output.writeInt(this.addedStickerFileIds[i]);
				}
			}
			output.writeInt(this.duration);
			output.writeInt(this.width);
			output.writeInt(this.height);
			output.writeBoolean(this.supportsStreaming);
			if (this.caption == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.caption.serialize(output);
			}
			output.writeInt(this.selfDestructTime);
			output.writeBoolean(this.hasSpoiler);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputMessageVideo inputMessageVideo = (InputMessageVideo) o;
			if (!Objects.equals(this.video, inputMessageVideo.video)) {
				return false;
			}
			if (!Objects.equals(this.thumbnail, inputMessageVideo.thumbnail)) {
				return false;
			}
			if (!Arrays.equals(this.addedStickerFileIds, inputMessageVideo.addedStickerFileIds)) {
				return false;
			}
			if (this.duration != inputMessageVideo.duration) {
				return false;
			}
			if (this.width != inputMessageVideo.width) {
				return false;
			}
			if (this.height != inputMessageVideo.height) {
				return false;
			}
			if (this.supportsStreaming != inputMessageVideo.supportsStreaming) {
				return false;
			}
			if (!Objects.equals(this.caption, inputMessageVideo.caption)) {
				return false;
			}
			if (this.selfDestructTime != inputMessageVideo.selfDestructTime) {
				return false;
			}
			if (this.hasSpoiler != inputMessageVideo.hasSpoiler) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.duration);
			result = result * 31 + (this.video == null ? 0 : this.video.hashCode());
			result = result * 31 + (this.thumbnail == null ? 0 : this.thumbnail.hashCode());
			result = result * 31 + (Arrays.hashCode(this.addedStickerFileIds));
			result = result * 31 + (this.caption == null ? 0 : this.caption.hashCode());
			return result;
		}
	}

	/**
	 * A video note message.
	**/
	public static final class InputMessageVideoNote extends InputMessageContent {


		/**
		 * Video note to be sent.
		**/
		public InputFile videoNote;

		/**
		 * Video thumbnail; pass null to skip thumbnail uploading.
		**/
		public InputThumbnail thumbnail;

		/**
		 * Duration of the video, in seconds.
		**/
		public int duration;

		/**
		 * Video width and height; must be positive and not greater than 640.
		**/
		public int length;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 279108859;

		/**
		 * A video note message.
		**/
		public InputMessageVideoNote() {}

		/**
		 * A video note message.
		 *
		 * @param videoNote Video note to be sent.
		 * @param thumbnail Video thumbnail; pass null to skip thumbnail uploading.
		 * @param duration Duration of the video, in seconds.
		 * @param length Video width and height; must be positive and not greater than 640.
		**/
		public InputMessageVideoNote(InputFile videoNote,
				InputThumbnail thumbnail,
				int duration,
				int length) {
			this.videoNote = videoNote;
			this.thumbnail = thumbnail;
			this.duration = duration;
			this.length = length;
		}

		/**
		 * A video note message.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputMessageVideoNote(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputFileId.CONSTRUCTOR: this.videoNote = new InputFileId(input); break;
					case InputFileRemote.CONSTRUCTOR: this.videoNote = new InputFileRemote(input); break;
					case InputFileLocal.CONSTRUCTOR: this.videoNote = new InputFileLocal(input); break;
					case InputFileGenerated.CONSTRUCTOR: this.videoNote = new InputFileGenerated(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				if (InputThumbnail.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.thumbnail = new InputThumbnail(input);
			}
			this.duration = input.readInt();
			this.length = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputMessageVideoNote.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputMessageVideoNote.CONSTRUCTOR);
			if (this.videoNote == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.videoNote.serialize(output);
			}
			if (this.thumbnail == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.thumbnail.serialize(output);
			}
			output.writeInt(this.duration);
			output.writeInt(this.length);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputMessageVideoNote inputMessageVideoNote = (InputMessageVideoNote) o;
			if (!Objects.equals(this.videoNote, inputMessageVideoNote.videoNote)) {
				return false;
			}
			if (!Objects.equals(this.thumbnail, inputMessageVideoNote.thumbnail)) {
				return false;
			}
			if (this.duration != inputMessageVideoNote.duration) {
				return false;
			}
			if (this.length != inputMessageVideoNote.length) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.duration);
			result = result * 31 + (this.videoNote == null ? 0 : this.videoNote.hashCode());
			result = result * 31 + (this.thumbnail == null ? 0 : this.thumbnail.hashCode());
			return result;
		}
	}

	/**
	 * A voice note message.
	**/
	public static final class InputMessageVoiceNote extends InputMessageContent {


		/**
		 * Voice note to be sent.
		**/
		public InputFile voiceNote;

		/**
		 * Duration of the voice note, in seconds.
		**/
		public int duration;

		/**
		 * Waveform representation of the voice note in 5-bit format.
		**/
		public byte[] waveform;

		/**
		 * Voice note caption; pass null to use an empty caption; 0-getOption(&quot;message_caption_length_max&quot;) characters.
		**/
		public FormattedText caption;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2136519657;

		/**
		 * A voice note message.
		**/
		public InputMessageVoiceNote() {}

		/**
		 * A voice note message.
		 *
		 * @param voiceNote Voice note to be sent.
		 * @param duration Duration of the voice note, in seconds.
		 * @param waveform Waveform representation of the voice note in 5-bit format.
		 * @param caption Voice note caption; pass null to use an empty caption; 0-getOption(&quot;message_caption_length_max&quot;) characters.
		**/
		public InputMessageVoiceNote(InputFile voiceNote,
				int duration,
				byte[] waveform,
				FormattedText caption) {
			this.voiceNote = voiceNote;
			this.duration = duration;
			this.waveform = waveform;
			this.caption = caption;
		}

		/**
		 * A voice note message.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputMessageVoiceNote(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputFileId.CONSTRUCTOR: this.voiceNote = new InputFileId(input); break;
					case InputFileRemote.CONSTRUCTOR: this.voiceNote = new InputFileRemote(input); break;
					case InputFileLocal.CONSTRUCTOR: this.voiceNote = new InputFileLocal(input); break;
					case InputFileGenerated.CONSTRUCTOR: this.voiceNote = new InputFileGenerated(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.duration = input.readInt();
			if (input.readBoolean()) {
				this.waveform = new byte[input.readInt()];
				input.readFully(this.waveform);
			}
			if (input.readBoolean()) {
				if (FormattedText.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.caption = new FormattedText(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputMessageVoiceNote.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputMessageVoiceNote.CONSTRUCTOR);
			if (this.voiceNote == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.voiceNote.serialize(output);
			}
			output.writeInt(this.duration);
			if (this.waveform == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.waveform.length);
				output.write(this.waveform);
			}
			if (this.caption == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.caption.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputMessageVoiceNote inputMessageVoiceNote = (InputMessageVoiceNote) o;
			if (!Objects.equals(this.voiceNote, inputMessageVoiceNote.voiceNote)) {
				return false;
			}
			if (this.duration != inputMessageVoiceNote.duration) {
				return false;
			}
			if (this.waveform != inputMessageVoiceNote.waveform) {
				return false;
			}
			if (!Objects.equals(this.caption, inputMessageVoiceNote.caption)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.duration);
			result = result * 31 + (this.voiceNote == null ? 0 : this.voiceNote.hashCode());
			result = result * 31 + (Arrays.hashCode(this.waveform));
			result = result * 31 + (this.caption == null ? 0 : this.caption.hashCode());
			return result;
		}
	}

	/**
	 * A message with a location.
	**/
	public static final class InputMessageLocation extends InputMessageContent {


		/**
		 * Location to be sent.
		**/
		public Location location;

		/**
		 * Period for which the location can be updated, in seconds; must be between 60 and 86400 for a live location and 0 otherwise.
		**/
		public int livePeriod;

		/**
		 * For live locations, a direction in which the location moves, in degrees; 1-360. Pass 0 if unknown.
		**/
		public int heading;

		/**
		 * For live locations, a maximum distance to another chat member for proximity alerts, in meters (0-100000). Pass 0 if the notification is disabled. Can&#039;t be enabled in channels and Saved Messages.
		**/
		public int proximityAlertRadius;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 648735088;

		/**
		 * A message with a location.
		**/
		public InputMessageLocation() {}

		/**
		 * A message with a location.
		 *
		 * @param location Location to be sent.
		 * @param livePeriod Period for which the location can be updated, in seconds; must be between 60 and 86400 for a live location and 0 otherwise.
		 * @param heading For live locations, a direction in which the location moves, in degrees; 1-360. Pass 0 if unknown.
		 * @param proximityAlertRadius For live locations, a maximum distance to another chat member for proximity alerts, in meters (0-100000). Pass 0 if the notification is disabled. Can&#039;t be enabled in channels and Saved Messages.
		**/
		public InputMessageLocation(Location location,
				int livePeriod,
				int heading,
				int proximityAlertRadius) {
			this.location = location;
			this.livePeriod = livePeriod;
			this.heading = heading;
			this.proximityAlertRadius = proximityAlertRadius;
		}

		/**
		 * A message with a location.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputMessageLocation(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Location.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.location = new Location(input);
			}
			this.livePeriod = input.readInt();
			this.heading = input.readInt();
			this.proximityAlertRadius = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputMessageLocation.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputMessageLocation.CONSTRUCTOR);
			if (this.location == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.location.serialize(output);
			}
			output.writeInt(this.livePeriod);
			output.writeInt(this.heading);
			output.writeInt(this.proximityAlertRadius);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputMessageLocation inputMessageLocation = (InputMessageLocation) o;
			if (!Objects.equals(this.location, inputMessageLocation.location)) {
				return false;
			}
			if (this.livePeriod != inputMessageLocation.livePeriod) {
				return false;
			}
			if (this.heading != inputMessageLocation.heading) {
				return false;
			}
			if (this.proximityAlertRadius != inputMessageLocation.proximityAlertRadius) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.livePeriod);
			result = result * 31 + (this.location == null ? 0 : this.location.hashCode());
			return result;
		}
	}

	/**
	 * A message with information about a venue.
	**/
	public static final class InputMessageVenue extends InputMessageContent {


		/**
		 * Venue to send.
		**/
		public Venue venue;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1447926269;

		/**
		 * A message with information about a venue.
		**/
		public InputMessageVenue() {}

		/**
		 * A message with information about a venue.
		 *
		 * @param venue Venue to send.
		**/
		public InputMessageVenue(Venue venue) {
			this.venue = venue;
		}

		/**
		 * A message with information about a venue.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputMessageVenue(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Venue.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.venue = new Venue(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputMessageVenue.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputMessageVenue.CONSTRUCTOR);
			if (this.venue == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.venue.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputMessageVenue inputMessageVenue = (InputMessageVenue) o;
			if (!Objects.equals(this.venue, inputMessageVenue.venue)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.venue == null ? 0 : this.venue.hashCode();
		}
	}

	/**
	 * A message containing a user contact.
	**/
	public static final class InputMessageContact extends InputMessageContent {


		/**
		 * Contact to send.
		**/
		public Contact contact;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -982446849;

		/**
		 * A message containing a user contact.
		**/
		public InputMessageContact() {}

		/**
		 * A message containing a user contact.
		 *
		 * @param contact Contact to send.
		**/
		public InputMessageContact(Contact contact) {
			this.contact = contact;
		}

		/**
		 * A message containing a user contact.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputMessageContact(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Contact.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.contact = new Contact(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputMessageContact.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputMessageContact.CONSTRUCTOR);
			if (this.contact == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.contact.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputMessageContact inputMessageContact = (InputMessageContact) o;
			if (!Objects.equals(this.contact, inputMessageContact.contact)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.contact == null ? 0 : this.contact.hashCode();
		}
	}

	/**
	 * A dice message.
	**/
	public static final class InputMessageDice extends InputMessageContent {


		/**
		 * Emoji on which the dice throw animation is based.
		**/
		public String emoji;

		/**
		 * True, if the chat message draft must be deleted.
		**/
		public boolean clearDraft;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 841574313;

		/**
		 * A dice message.
		**/
		public InputMessageDice() {}

		/**
		 * A dice message.
		 *
		 * @param emoji Emoji on which the dice throw animation is based.
		 * @param clearDraft True, if the chat message draft must be deleted.
		**/
		public InputMessageDice(String emoji, boolean clearDraft) {
			this.emoji = emoji;
			this.clearDraft = clearDraft;
		}

		/**
		 * A dice message.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputMessageDice(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] emojiTmp = new byte[input.readInt()];
				input.readFully(emojiTmp);
				this.emoji = new String(emojiTmp, StandardCharsets.UTF_8);
			}
			this.clearDraft = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputMessageDice.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputMessageDice.CONSTRUCTOR);
			if (this.emoji == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] emojiTmp = this.emoji.getBytes(StandardCharsets.UTF_8);
				output.writeInt(emojiTmp.length);
				output.write(emojiTmp);
			}
			output.writeBoolean(this.clearDraft);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputMessageDice inputMessageDice = (InputMessageDice) o;
			if (this.emoji != inputMessageDice.emoji) {
				return false;
			}
			if (this.clearDraft != inputMessageDice.clearDraft) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.clearDraft);
			result = result * 31 + (this.emoji == null ? 0 : this.emoji.hashCode());
			return result;
		}
	}

	/**
	 * A message with a game; not supported for channels or secret chats.
	**/
	public static final class InputMessageGame extends InputMessageContent {


		/**
		 * User identifier of the bot that owns the game.
		**/
		public long botUserId;

		/**
		 * Short name of the game.
		**/
		public String gameShortName;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1252944610;

		/**
		 * A message with a game; not supported for channels or secret chats.
		**/
		public InputMessageGame() {}

		/**
		 * A message with a game; not supported for channels or secret chats.
		 *
		 * @param botUserId User identifier of the bot that owns the game.
		 * @param gameShortName Short name of the game.
		**/
		public InputMessageGame(long botUserId, String gameShortName) {
			this.botUserId = botUserId;
			this.gameShortName = gameShortName;
		}

		/**
		 * A message with a game; not supported for channels or secret chats.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputMessageGame(DataInput input) throws IOException {
			this.botUserId = input.readLong();
			if (input.readBoolean()) {
				byte[] gameShortNameTmp = new byte[input.readInt()];
				input.readFully(gameShortNameTmp);
				this.gameShortName = new String(gameShortNameTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputMessageGame.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputMessageGame.CONSTRUCTOR);
			output.writeLong(this.botUserId);
			if (this.gameShortName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] gameShortNameTmp = this.gameShortName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(gameShortNameTmp.length);
				output.write(gameShortNameTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputMessageGame inputMessageGame = (InputMessageGame) o;
			if (this.botUserId != inputMessageGame.botUserId) {
				return false;
			}
			if (this.gameShortName != inputMessageGame.gameShortName) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.botUserId);
			result = result * 31 + (this.gameShortName == null ? 0 : this.gameShortName.hashCode());
			return result;
		}
	}

	/**
	 * A message with an invoice; can be used only by bots.
	**/
	public static final class InputMessageInvoice extends InputMessageContent {


		/**
		 * Invoice.
		**/
		public Invoice invoice;

		/**
		 * Product title; 1-32 characters.
		**/
		public String title;

		/**
		 * Product description; 0-255 characters.
		**/
		public String description;

		/**
		 * Product photo URL; optional.
		**/
		public String photoUrl;

		/**
		 * Product photo size.
		**/
		public int photoSize;

		/**
		 * Product photo width.
		**/
		public int photoWidth;

		/**
		 * Product photo height.
		**/
		public int photoHeight;

		/**
		 * The invoice payload.
		**/
		public byte[] payload;

		/**
		 * Payment provider token.
		**/
		public String providerToken;

		/**
		 * JSON-encoded data about the invoice, which will be shared with the payment provider.
		**/
		public String providerData;

		/**
		 * Unique invoice bot deep link parameter for the generation of this invoice. If empty, it would be possible to pay directly from forwards of the invoice message.
		**/
		public String startParameter;

		/**
		 * The content of extended media attached to the invoice. The content of the message to be sent. Must be one of the following types: inputMessagePhoto, inputMessageVideo.
		**/
		public InputMessageContent extendedMediaContent;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 885857632;

		/**
		 * A message with an invoice; can be used only by bots.
		**/
		public InputMessageInvoice() {}

		/**
		 * A message with an invoice; can be used only by bots.
		 *
		 * @param invoice Invoice.
		 * @param title Product title; 1-32 characters.
		 * @param description Product description; 0-255 characters.
		 * @param photoUrl Product photo URL; optional.
		 * @param photoSize Product photo size.
		 * @param photoWidth Product photo width.
		 * @param photoHeight Product photo height.
		 * @param payload The invoice payload.
		 * @param providerToken Payment provider token.
		 * @param providerData JSON-encoded data about the invoice, which will be shared with the payment provider.
		 * @param startParameter Unique invoice bot deep link parameter for the generation of this invoice. If empty, it would be possible to pay directly from forwards of the invoice message.
		 * @param extendedMediaContent The content of extended media attached to the invoice. The content of the message to be sent. Must be one of the following types: inputMessagePhoto, inputMessageVideo.
		**/
		public InputMessageInvoice(Invoice invoice,
				String title,
				String description,
				String photoUrl,
				int photoSize,
				int photoWidth,
				int photoHeight,
				byte[] payload,
				String providerToken,
				String providerData,
				String startParameter,
				InputMessageContent extendedMediaContent) {
			this.invoice = invoice;
			this.title = title;
			this.description = description;
			this.photoUrl = photoUrl;
			this.photoSize = photoSize;
			this.photoWidth = photoWidth;
			this.photoHeight = photoHeight;
			this.payload = payload;
			this.providerToken = providerToken;
			this.providerData = providerData;
			this.startParameter = startParameter;
			this.extendedMediaContent = extendedMediaContent;
		}

		/**
		 * A message with an invoice; can be used only by bots.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputMessageInvoice(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Invoice.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.invoice = new Invoice(input);
			}
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] descriptionTmp = new byte[input.readInt()];
				input.readFully(descriptionTmp);
				this.description = new String(descriptionTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] photoUrlTmp = new byte[input.readInt()];
				input.readFully(photoUrlTmp);
				this.photoUrl = new String(photoUrlTmp, StandardCharsets.UTF_8);
			}
			this.photoSize = input.readInt();
			this.photoWidth = input.readInt();
			this.photoHeight = input.readInt();
			if (input.readBoolean()) {
				this.payload = new byte[input.readInt()];
				input.readFully(this.payload);
			}
			if (input.readBoolean()) {
				byte[] providerTokenTmp = new byte[input.readInt()];
				input.readFully(providerTokenTmp);
				this.providerToken = new String(providerTokenTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] providerDataTmp = new byte[input.readInt()];
				input.readFully(providerDataTmp);
				this.providerData = new String(providerDataTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] startParameterTmp = new byte[input.readInt()];
				input.readFully(startParameterTmp);
				this.startParameter = new String(startParameterTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputMessageText.CONSTRUCTOR: this.extendedMediaContent = new InputMessageText(input); break;
					case InputMessageAnimation.CONSTRUCTOR: this.extendedMediaContent = new InputMessageAnimation(input); break;
					case InputMessageAudio.CONSTRUCTOR: this.extendedMediaContent = new InputMessageAudio(input); break;
					case InputMessageDocument.CONSTRUCTOR: this.extendedMediaContent = new InputMessageDocument(input); break;
					case InputMessagePhoto.CONSTRUCTOR: this.extendedMediaContent = new InputMessagePhoto(input); break;
					case InputMessageSticker.CONSTRUCTOR: this.extendedMediaContent = new InputMessageSticker(input); break;
					case InputMessageVideo.CONSTRUCTOR: this.extendedMediaContent = new InputMessageVideo(input); break;
					case InputMessageVideoNote.CONSTRUCTOR: this.extendedMediaContent = new InputMessageVideoNote(input); break;
					case InputMessageVoiceNote.CONSTRUCTOR: this.extendedMediaContent = new InputMessageVoiceNote(input); break;
					case InputMessageLocation.CONSTRUCTOR: this.extendedMediaContent = new InputMessageLocation(input); break;
					case InputMessageVenue.CONSTRUCTOR: this.extendedMediaContent = new InputMessageVenue(input); break;
					case InputMessageContact.CONSTRUCTOR: this.extendedMediaContent = new InputMessageContact(input); break;
					case InputMessageDice.CONSTRUCTOR: this.extendedMediaContent = new InputMessageDice(input); break;
					case InputMessageGame.CONSTRUCTOR: this.extendedMediaContent = new InputMessageGame(input); break;
					case InputMessageInvoice.CONSTRUCTOR: this.extendedMediaContent = new InputMessageInvoice(input); break;
					case InputMessagePoll.CONSTRUCTOR: this.extendedMediaContent = new InputMessagePoll(input); break;
					case InputMessageForwarded.CONSTRUCTOR: this.extendedMediaContent = new InputMessageForwarded(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputMessageInvoice.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputMessageInvoice.CONSTRUCTOR);
			if (this.invoice == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.invoice.serialize(output);
			}
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
			if (this.description == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] descriptionTmp = this.description.getBytes(StandardCharsets.UTF_8);
				output.writeInt(descriptionTmp.length);
				output.write(descriptionTmp);
			}
			if (this.photoUrl == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] photoUrlTmp = this.photoUrl.getBytes(StandardCharsets.UTF_8);
				output.writeInt(photoUrlTmp.length);
				output.write(photoUrlTmp);
			}
			output.writeInt(this.photoSize);
			output.writeInt(this.photoWidth);
			output.writeInt(this.photoHeight);
			if (this.payload == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.payload.length);
				output.write(this.payload);
			}
			if (this.providerToken == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] providerTokenTmp = this.providerToken.getBytes(StandardCharsets.UTF_8);
				output.writeInt(providerTokenTmp.length);
				output.write(providerTokenTmp);
			}
			if (this.providerData == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] providerDataTmp = this.providerData.getBytes(StandardCharsets.UTF_8);
				output.writeInt(providerDataTmp.length);
				output.write(providerDataTmp);
			}
			if (this.startParameter == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] startParameterTmp = this.startParameter.getBytes(StandardCharsets.UTF_8);
				output.writeInt(startParameterTmp.length);
				output.write(startParameterTmp);
			}
			if (this.extendedMediaContent == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.extendedMediaContent.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputMessageInvoice inputMessageInvoice = (InputMessageInvoice) o;
			if (!Objects.equals(this.invoice, inputMessageInvoice.invoice)) {
				return false;
			}
			if (this.title != inputMessageInvoice.title) {
				return false;
			}
			if (this.description != inputMessageInvoice.description) {
				return false;
			}
			if (this.photoUrl != inputMessageInvoice.photoUrl) {
				return false;
			}
			if (this.photoSize != inputMessageInvoice.photoSize) {
				return false;
			}
			if (this.photoWidth != inputMessageInvoice.photoWidth) {
				return false;
			}
			if (this.photoHeight != inputMessageInvoice.photoHeight) {
				return false;
			}
			if (this.payload != inputMessageInvoice.payload) {
				return false;
			}
			if (this.providerToken != inputMessageInvoice.providerToken) {
				return false;
			}
			if (this.providerData != inputMessageInvoice.providerData) {
				return false;
			}
			if (this.startParameter != inputMessageInvoice.startParameter) {
				return false;
			}
			if (!Objects.equals(this.extendedMediaContent, inputMessageInvoice.extendedMediaContent)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.photoSize);
			result = result * 31 + (this.invoice == null ? 0 : this.invoice.hashCode());
			result = result * 31 + (this.title == null ? 0 : this.title.hashCode());
			result = result * 31 + (this.description == null ? 0 : this.description.hashCode());
			result = result * 31 + (this.photoUrl == null ? 0 : this.photoUrl.hashCode());
			result = result * 31 + (Arrays.hashCode(this.payload));
			result = result * 31 + (this.providerToken == null ? 0 : this.providerToken.hashCode());
			result = result * 31 + (this.providerData == null ? 0 : this.providerData.hashCode());
			result = result * 31 + (this.startParameter == null ? 0 : this.startParameter.hashCode());
			result = result * 31 + (this.extendedMediaContent == null ? 0 : this.extendedMediaContent.hashCode());
			return result;
		}
	}

	/**
	 * A message with a poll. Polls can&#039;t be sent to secret chats.
	 * Polls can be sent only to a private chat with a bot.
	**/
	public static final class InputMessagePoll extends InputMessageContent {


		/**
		 * Poll question; 1-255 characters (up to 300 characters for bots).
		**/
		public String question;

		/**
		 * List of poll answer options, 2-10 strings 1-100 characters each.
		**/
		public String[] options;

		/**
		 * True, if the poll voters are anonymous. Non-anonymous polls can&#039;t be sent or forwarded to channels.
		**/
		public boolean isAnonymous;

		/**
		 * Type of the poll.
		**/
		public PollType type;

		/**
		 * Amount of time the poll will be active after creation, in seconds; for bots only.
		**/
		public int openPeriod;

		/**
		 * Point in time (Unix timestamp) when the poll will automatically be closed; for bots only.
		**/
		public int closeDate;

		/**
		 * True, if the poll needs to be sent already closed; for bots only.
		**/
		public boolean isClosed;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2054629900;

		/**
		 * A message with a poll. Polls can&#039;t be sent to secret chats. Polls can be sent only to a private chat with a bot.
		**/
		public InputMessagePoll() {}

		/**
		 * A message with a poll. Polls can&#039;t be sent to secret chats. Polls can be sent only to a private chat with a bot.
		 *
		 * @param question Poll question; 1-255 characters (up to 300 characters for bots).
		 * @param options List of poll answer options, 2-10 strings 1-100 characters each.
		 * @param isAnonymous True, if the poll voters are anonymous. Non-anonymous polls can&#039;t be sent or forwarded to channels.
		 * @param type Type of the poll.
		 * @param openPeriod Amount of time the poll will be active after creation, in seconds; for bots only.
		 * @param closeDate Point in time (Unix timestamp) when the poll will automatically be closed; for bots only.
		 * @param isClosed True, if the poll needs to be sent already closed; for bots only.
		**/
		public InputMessagePoll(String question,
				String[] options,
				boolean isAnonymous,
				PollType type,
				int openPeriod,
				int closeDate,
				boolean isClosed) {
			this.question = question;
			this.options = options;
			this.isAnonymous = isAnonymous;
			this.type = type;
			this.openPeriod = openPeriod;
			this.closeDate = closeDate;
			this.isClosed = isClosed;
		}

		/**
		 * A message with a poll. Polls can&#039;t be sent to secret chats. Polls can be sent only to a private chat with a bot.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputMessagePoll(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] questionTmp = new byte[input.readInt()];
				input.readFully(questionTmp);
				this.question = new String(questionTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				this.options = new String[input.readInt()];
				for (int i = 0; i < this.options.length; i++) {
					byte[] optionsTmp = new byte[input.readInt()];
					input.readFully(optionsTmp);
					this.options[i] = new String(optionsTmp, StandardCharsets.UTF_8);
				}
			}
			this.isAnonymous = input.readBoolean();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case PollTypeRegular.CONSTRUCTOR: this.type = new PollTypeRegular(input); break;
					case PollTypeQuiz.CONSTRUCTOR: this.type = new PollTypeQuiz(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.openPeriod = input.readInt();
			this.closeDate = input.readInt();
			this.isClosed = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputMessagePoll.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputMessagePoll.CONSTRUCTOR);
			if (this.question == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] questionTmp = this.question.getBytes(StandardCharsets.UTF_8);
				output.writeInt(questionTmp.length);
				output.write(questionTmp);
			}
			if (this.options == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.options.length);
				for (int i = 0; i < this.options.length; i++) {
					byte[] optionsTmp = this.options[i].getBytes(StandardCharsets.UTF_8);
					output.writeInt(optionsTmp.length);
					output.write(optionsTmp);
				}
			}
			output.writeBoolean(this.isAnonymous);
			if (this.type == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.type.serialize(output);
			}
			output.writeInt(this.openPeriod);
			output.writeInt(this.closeDate);
			output.writeBoolean(this.isClosed);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputMessagePoll inputMessagePoll = (InputMessagePoll) o;
			if (this.question != inputMessagePoll.question) {
				return false;
			}
			if (!Arrays.equals(this.options, inputMessagePoll.options)) {
				return false;
			}
			if (this.isAnonymous != inputMessagePoll.isAnonymous) {
				return false;
			}
			if (!Objects.equals(this.type, inputMessagePoll.type)) {
				return false;
			}
			if (this.openPeriod != inputMessagePoll.openPeriod) {
				return false;
			}
			if (this.closeDate != inputMessagePoll.closeDate) {
				return false;
			}
			if (this.isClosed != inputMessagePoll.isClosed) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isAnonymous);
			result = result * 31 + (this.question == null ? 0 : this.question.hashCode());
			result = result * 31 + (Arrays.hashCode(this.options));
			result = result * 31 + (this.type == null ? 0 : this.type.hashCode());
			return result;
		}
	}

	/**
	 * A forwarded message.
	**/
	public static final class InputMessageForwarded extends InputMessageContent {


		/**
		 * Identifier for the chat this forwarded message came from.
		**/
		public long fromChatId;

		/**
		 * Identifier of the message to forward.
		**/
		public long messageId;

		/**
		 * True, if a game message is being shared from a launched game; applies only to game messages.
		**/
		public boolean inGameShare;

		/**
		 * Options to be used to copy content of the message without reference to the original sender; pass null to forward the message as usual.
		**/
		public MessageCopyOptions copyOptions;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1696232440;

		/**
		 * A forwarded message.
		**/
		public InputMessageForwarded() {}

		/**
		 * A forwarded message.
		 *
		 * @param fromChatId Identifier for the chat this forwarded message came from.
		 * @param messageId Identifier of the message to forward.
		 * @param inGameShare True, if a game message is being shared from a launched game; applies only to game messages.
		 * @param copyOptions Options to be used to copy content of the message without reference to the original sender; pass null to forward the message as usual.
		**/
		public InputMessageForwarded(long fromChatId,
				long messageId,
				boolean inGameShare,
				MessageCopyOptions copyOptions) {
			this.fromChatId = fromChatId;
			this.messageId = messageId;
			this.inGameShare = inGameShare;
			this.copyOptions = copyOptions;
		}

		/**
		 * A forwarded message.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputMessageForwarded(DataInput input) throws IOException {
			this.fromChatId = input.readLong();
			this.messageId = input.readLong();
			this.inGameShare = input.readBoolean();
			if (input.readBoolean()) {
				if (MessageCopyOptions.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.copyOptions = new MessageCopyOptions(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputMessageForwarded.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputMessageForwarded.CONSTRUCTOR);
			output.writeLong(this.fromChatId);
			output.writeLong(this.messageId);
			output.writeBoolean(this.inGameShare);
			if (this.copyOptions == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.copyOptions.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputMessageForwarded inputMessageForwarded = (InputMessageForwarded) o;
			if (this.fromChatId != inputMessageForwarded.fromChatId) {
				return false;
			}
			if (this.messageId != inputMessageForwarded.messageId) {
				return false;
			}
			if (this.inGameShare != inputMessageForwarded.inGameShare) {
				return false;
			}
			if (!Objects.equals(this.copyOptions, inputMessageForwarded.copyOptions)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.fromChatId);
			result = result * 31 + (this.copyOptions == null ? 0 : this.copyOptions.hashCode());
			return result;
		}
	}

	/**
	 * A Telegram Passport element to be saved containing the user&#039;s
	 * personal details.
	**/
	public static final class InputPassportElementPersonalDetails extends InputPassportElement {


		/**
		 * Personal details of the user.
		**/
		public PersonalDetails personalDetails;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 164791359;

		/**
		 * A Telegram Passport element to be saved containing the user&#039;s personal details.
		**/
		public InputPassportElementPersonalDetails() {}

		/**
		 * A Telegram Passport element to be saved containing the user&#039;s personal details.
		 *
		 * @param personalDetails Personal details of the user.
		**/
		public InputPassportElementPersonalDetails(PersonalDetails personalDetails) {
			this.personalDetails = personalDetails;
		}

		/**
		 * A Telegram Passport element to be saved containing the user&#039;s personal details.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputPassportElementPersonalDetails(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (PersonalDetails.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.personalDetails = new PersonalDetails(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputPassportElementPersonalDetails.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputPassportElementPersonalDetails.CONSTRUCTOR);
			if (this.personalDetails == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.personalDetails.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputPassportElementPersonalDetails inputPassportElementPersonalDetails = (InputPassportElementPersonalDetails) o;
			if (!Objects.equals(this.personalDetails, inputPassportElementPersonalDetails.personalDetails)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.personalDetails == null ? 0 : this.personalDetails.hashCode();
		}
	}

	/**
	 * A Telegram Passport element to be saved containing the user&#039;s
	 * passport.
	**/
	public static final class InputPassportElementPassport extends InputPassportElement {


		/**
		 * The passport to be saved.
		**/
		public InputIdentityDocument passport;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -497011356;

		/**
		 * A Telegram Passport element to be saved containing the user&#039;s passport.
		**/
		public InputPassportElementPassport() {}

		/**
		 * A Telegram Passport element to be saved containing the user&#039;s passport.
		 *
		 * @param passport The passport to be saved.
		**/
		public InputPassportElementPassport(InputIdentityDocument passport) {
			this.passport = passport;
		}

		/**
		 * A Telegram Passport element to be saved containing the user&#039;s passport.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputPassportElementPassport(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (InputIdentityDocument.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.passport = new InputIdentityDocument(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputPassportElementPassport.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputPassportElementPassport.CONSTRUCTOR);
			if (this.passport == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.passport.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputPassportElementPassport inputPassportElementPassport = (InputPassportElementPassport) o;
			if (!Objects.equals(this.passport, inputPassportElementPassport.passport)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.passport == null ? 0 : this.passport.hashCode();
		}
	}

	/**
	 * A Telegram Passport element to be saved containing the user&#039;s
	 * driver license.
	**/
	public static final class InputPassportElementDriverLicense extends InputPassportElement {


		/**
		 * The driver license to be saved.
		**/
		public InputIdentityDocument driverLicense;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 304813264;

		/**
		 * A Telegram Passport element to be saved containing the user&#039;s driver license.
		**/
		public InputPassportElementDriverLicense() {}

		/**
		 * A Telegram Passport element to be saved containing the user&#039;s driver license.
		 *
		 * @param driverLicense The driver license to be saved.
		**/
		public InputPassportElementDriverLicense(InputIdentityDocument driverLicense) {
			this.driverLicense = driverLicense;
		}

		/**
		 * A Telegram Passport element to be saved containing the user&#039;s driver license.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputPassportElementDriverLicense(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (InputIdentityDocument.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.driverLicense = new InputIdentityDocument(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputPassportElementDriverLicense.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputPassportElementDriverLicense.CONSTRUCTOR);
			if (this.driverLicense == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.driverLicense.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputPassportElementDriverLicense inputPassportElementDriverLicense = (InputPassportElementDriverLicense) o;
			if (!Objects.equals(this.driverLicense, inputPassportElementDriverLicense.driverLicense)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.driverLicense == null ? 0 : this.driverLicense.hashCode();
		}
	}

	/**
	 * A Telegram Passport element to be saved containing the user&#039;s
	 * identity card.
	**/
	public static final class InputPassportElementIdentityCard extends InputPassportElement {


		/**
		 * The identity card to be saved.
		**/
		public InputIdentityDocument identityCard;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -9963390;

		/**
		 * A Telegram Passport element to be saved containing the user&#039;s identity card.
		**/
		public InputPassportElementIdentityCard() {}

		/**
		 * A Telegram Passport element to be saved containing the user&#039;s identity card.
		 *
		 * @param identityCard The identity card to be saved.
		**/
		public InputPassportElementIdentityCard(InputIdentityDocument identityCard) {
			this.identityCard = identityCard;
		}

		/**
		 * A Telegram Passport element to be saved containing the user&#039;s identity card.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputPassportElementIdentityCard(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (InputIdentityDocument.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.identityCard = new InputIdentityDocument(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputPassportElementIdentityCard.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputPassportElementIdentityCard.CONSTRUCTOR);
			if (this.identityCard == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.identityCard.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputPassportElementIdentityCard inputPassportElementIdentityCard = (InputPassportElementIdentityCard) o;
			if (!Objects.equals(this.identityCard, inputPassportElementIdentityCard.identityCard)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.identityCard == null ? 0 : this.identityCard.hashCode();
		}
	}

	/**
	 * A Telegram Passport element to be saved containing the user&#039;s
	 * internal passport.
	**/
	public static final class InputPassportElementInternalPassport extends InputPassportElement {


		/**
		 * The internal passport to be saved.
		**/
		public InputIdentityDocument internalPassport;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 715360043;

		/**
		 * A Telegram Passport element to be saved containing the user&#039;s internal passport.
		**/
		public InputPassportElementInternalPassport() {}

		/**
		 * A Telegram Passport element to be saved containing the user&#039;s internal passport.
		 *
		 * @param internalPassport The internal passport to be saved.
		**/
		public InputPassportElementInternalPassport(InputIdentityDocument internalPassport) {
			this.internalPassport = internalPassport;
		}

		/**
		 * A Telegram Passport element to be saved containing the user&#039;s internal passport.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputPassportElementInternalPassport(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (InputIdentityDocument.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.internalPassport = new InputIdentityDocument(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputPassportElementInternalPassport.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputPassportElementInternalPassport.CONSTRUCTOR);
			if (this.internalPassport == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.internalPassport.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputPassportElementInternalPassport inputPassportElementInternalPassport = (InputPassportElementInternalPassport) o;
			if (!Objects.equals(this.internalPassport, inputPassportElementInternalPassport.internalPassport)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.internalPassport == null ? 0 : this.internalPassport.hashCode();
		}
	}

	/**
	 * A Telegram Passport element to be saved containing the user&#039;s
	 * address.
	**/
	public static final class InputPassportElementAddress extends InputPassportElement {


		/**
		 * The address to be saved.
		**/
		public Address address;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 461630480;

		/**
		 * A Telegram Passport element to be saved containing the user&#039;s address.
		**/
		public InputPassportElementAddress() {}

		/**
		 * A Telegram Passport element to be saved containing the user&#039;s address.
		 *
		 * @param address The address to be saved.
		**/
		public InputPassportElementAddress(Address address) {
			this.address = address;
		}

		/**
		 * A Telegram Passport element to be saved containing the user&#039;s address.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputPassportElementAddress(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Address.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.address = new Address(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputPassportElementAddress.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputPassportElementAddress.CONSTRUCTOR);
			if (this.address == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.address.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputPassportElementAddress inputPassportElementAddress = (InputPassportElementAddress) o;
			if (!Objects.equals(this.address, inputPassportElementAddress.address)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.address == null ? 0 : this.address.hashCode();
		}
	}

	/**
	 * A Telegram Passport element to be saved containing the user&#039;s
	 * utility bill.
	**/
	public static final class InputPassportElementUtilityBill extends InputPassportElement {


		/**
		 * The utility bill to be saved.
		**/
		public InputPersonalDocument utilityBill;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1389203841;

		/**
		 * A Telegram Passport element to be saved containing the user&#039;s utility bill.
		**/
		public InputPassportElementUtilityBill() {}

		/**
		 * A Telegram Passport element to be saved containing the user&#039;s utility bill.
		 *
		 * @param utilityBill The utility bill to be saved.
		**/
		public InputPassportElementUtilityBill(InputPersonalDocument utilityBill) {
			this.utilityBill = utilityBill;
		}

		/**
		 * A Telegram Passport element to be saved containing the user&#039;s utility bill.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputPassportElementUtilityBill(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (InputPersonalDocument.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.utilityBill = new InputPersonalDocument(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputPassportElementUtilityBill.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputPassportElementUtilityBill.CONSTRUCTOR);
			if (this.utilityBill == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.utilityBill.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputPassportElementUtilityBill inputPassportElementUtilityBill = (InputPassportElementUtilityBill) o;
			if (!Objects.equals(this.utilityBill, inputPassportElementUtilityBill.utilityBill)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.utilityBill == null ? 0 : this.utilityBill.hashCode();
		}
	}

	/**
	 * A Telegram Passport element to be saved containing the user&#039;s
	 * bank statement.
	**/
	public static final class InputPassportElementBankStatement extends InputPassportElement {


		/**
		 * The bank statement to be saved.
		**/
		public InputPersonalDocument bankStatement;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -26585208;

		/**
		 * A Telegram Passport element to be saved containing the user&#039;s bank statement.
		**/
		public InputPassportElementBankStatement() {}

		/**
		 * A Telegram Passport element to be saved containing the user&#039;s bank statement.
		 *
		 * @param bankStatement The bank statement to be saved.
		**/
		public InputPassportElementBankStatement(InputPersonalDocument bankStatement) {
			this.bankStatement = bankStatement;
		}

		/**
		 * A Telegram Passport element to be saved containing the user&#039;s bank statement.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputPassportElementBankStatement(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (InputPersonalDocument.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.bankStatement = new InputPersonalDocument(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputPassportElementBankStatement.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputPassportElementBankStatement.CONSTRUCTOR);
			if (this.bankStatement == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.bankStatement.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputPassportElementBankStatement inputPassportElementBankStatement = (InputPassportElementBankStatement) o;
			if (!Objects.equals(this.bankStatement, inputPassportElementBankStatement.bankStatement)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.bankStatement == null ? 0 : this.bankStatement.hashCode();
		}
	}

	/**
	 * A Telegram Passport element to be saved containing the user&#039;s
	 * rental agreement.
	**/
	public static final class InputPassportElementRentalAgreement extends InputPassportElement {


		/**
		 * The rental agreement to be saved.
		**/
		public InputPersonalDocument rentalAgreement;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1736154155;

		/**
		 * A Telegram Passport element to be saved containing the user&#039;s rental agreement.
		**/
		public InputPassportElementRentalAgreement() {}

		/**
		 * A Telegram Passport element to be saved containing the user&#039;s rental agreement.
		 *
		 * @param rentalAgreement The rental agreement to be saved.
		**/
		public InputPassportElementRentalAgreement(InputPersonalDocument rentalAgreement) {
			this.rentalAgreement = rentalAgreement;
		}

		/**
		 * A Telegram Passport element to be saved containing the user&#039;s rental agreement.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputPassportElementRentalAgreement(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (InputPersonalDocument.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.rentalAgreement = new InputPersonalDocument(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputPassportElementRentalAgreement.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputPassportElementRentalAgreement.CONSTRUCTOR);
			if (this.rentalAgreement == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.rentalAgreement.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputPassportElementRentalAgreement inputPassportElementRentalAgreement = (InputPassportElementRentalAgreement) o;
			if (!Objects.equals(this.rentalAgreement, inputPassportElementRentalAgreement.rentalAgreement)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.rentalAgreement == null ? 0 : this.rentalAgreement.hashCode();
		}
	}

	/**
	 * A Telegram Passport element to be saved containing the user&#039;s
	 * passport registration.
	**/
	public static final class InputPassportElementPassportRegistration extends InputPassportElement {


		/**
		 * The passport registration page to be saved.
		**/
		public InputPersonalDocument passportRegistration;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1314562128;

		/**
		 * A Telegram Passport element to be saved containing the user&#039;s passport registration.
		**/
		public InputPassportElementPassportRegistration() {}

		/**
		 * A Telegram Passport element to be saved containing the user&#039;s passport registration.
		 *
		 * @param passportRegistration The passport registration page to be saved.
		**/
		public InputPassportElementPassportRegistration(InputPersonalDocument passportRegistration) {
			this.passportRegistration = passportRegistration;
		}

		/**
		 * A Telegram Passport element to be saved containing the user&#039;s passport registration.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputPassportElementPassportRegistration(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (InputPersonalDocument.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.passportRegistration = new InputPersonalDocument(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputPassportElementPassportRegistration.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputPassportElementPassportRegistration.CONSTRUCTOR);
			if (this.passportRegistration == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.passportRegistration.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputPassportElementPassportRegistration inputPassportElementPassportRegistration = (InputPassportElementPassportRegistration) o;
			if (!Objects.equals(this.passportRegistration, inputPassportElementPassportRegistration.passportRegistration)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.passportRegistration == null ? 0 : this.passportRegistration.hashCode();
		}
	}

	/**
	 * A Telegram Passport element to be saved containing the user&#039;s
	 * temporary registration.
	**/
	public static final class InputPassportElementTemporaryRegistration extends InputPassportElement {


		/**
		 * The temporary registration document to be saved.
		**/
		public InputPersonalDocument temporaryRegistration;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1913238047;

		/**
		 * A Telegram Passport element to be saved containing the user&#039;s temporary registration.
		**/
		public InputPassportElementTemporaryRegistration() {}

		/**
		 * A Telegram Passport element to be saved containing the user&#039;s temporary registration.
		 *
		 * @param temporaryRegistration The temporary registration document to be saved.
		**/
		public InputPassportElementTemporaryRegistration(InputPersonalDocument temporaryRegistration) {
			this.temporaryRegistration = temporaryRegistration;
		}

		/**
		 * A Telegram Passport element to be saved containing the user&#039;s temporary registration.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputPassportElementTemporaryRegistration(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (InputPersonalDocument.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.temporaryRegistration = new InputPersonalDocument(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputPassportElementTemporaryRegistration.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputPassportElementTemporaryRegistration.CONSTRUCTOR);
			if (this.temporaryRegistration == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.temporaryRegistration.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputPassportElementTemporaryRegistration inputPassportElementTemporaryRegistration = (InputPassportElementTemporaryRegistration) o;
			if (!Objects.equals(this.temporaryRegistration, inputPassportElementTemporaryRegistration.temporaryRegistration)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.temporaryRegistration == null ? 0 : this.temporaryRegistration.hashCode();
		}
	}

	/**
	 * A Telegram Passport element to be saved containing the user&#039;s
	 * phone number.
	**/
	public static final class InputPassportElementPhoneNumber extends InputPassportElement {


		/**
		 * The phone number to be saved.
		**/
		public String phoneNumber;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1319357497;

		/**
		 * A Telegram Passport element to be saved containing the user&#039;s phone number.
		**/
		public InputPassportElementPhoneNumber() {}

		/**
		 * A Telegram Passport element to be saved containing the user&#039;s phone number.
		 *
		 * @param phoneNumber The phone number to be saved.
		**/
		public InputPassportElementPhoneNumber(String phoneNumber) {
			this.phoneNumber = phoneNumber;
		}

		/**
		 * A Telegram Passport element to be saved containing the user&#039;s phone number.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputPassportElementPhoneNumber(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] phoneNumberTmp = new byte[input.readInt()];
				input.readFully(phoneNumberTmp);
				this.phoneNumber = new String(phoneNumberTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputPassportElementPhoneNumber.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputPassportElementPhoneNumber.CONSTRUCTOR);
			if (this.phoneNumber == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] phoneNumberTmp = this.phoneNumber.getBytes(StandardCharsets.UTF_8);
				output.writeInt(phoneNumberTmp.length);
				output.write(phoneNumberTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputPassportElementPhoneNumber inputPassportElementPhoneNumber = (InputPassportElementPhoneNumber) o;
			if (this.phoneNumber != inputPassportElementPhoneNumber.phoneNumber) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.phoneNumber == null ? 0 : this.phoneNumber.hashCode();
		}
	}

	/**
	 * A Telegram Passport element to be saved containing the user&#039;s
	 * email address.
	**/
	public static final class InputPassportElementEmailAddress extends InputPassportElement {


		/**
		 * The email address to be saved.
		**/
		public String emailAddress;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -248605659;

		/**
		 * A Telegram Passport element to be saved containing the user&#039;s email address.
		**/
		public InputPassportElementEmailAddress() {}

		/**
		 * A Telegram Passport element to be saved containing the user&#039;s email address.
		 *
		 * @param emailAddress The email address to be saved.
		**/
		public InputPassportElementEmailAddress(String emailAddress) {
			this.emailAddress = emailAddress;
		}

		/**
		 * A Telegram Passport element to be saved containing the user&#039;s email address.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputPassportElementEmailAddress(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] emailAddressTmp = new byte[input.readInt()];
				input.readFully(emailAddressTmp);
				this.emailAddress = new String(emailAddressTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputPassportElementEmailAddress.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputPassportElementEmailAddress.CONSTRUCTOR);
			if (this.emailAddress == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] emailAddressTmp = this.emailAddress.getBytes(StandardCharsets.UTF_8);
				output.writeInt(emailAddressTmp.length);
				output.write(emailAddressTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputPassportElementEmailAddress inputPassportElementEmailAddress = (InputPassportElementEmailAddress) o;
			if (this.emailAddress != inputPassportElementEmailAddress.emailAddress) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.emailAddress == null ? 0 : this.emailAddress.hashCode();
		}
	}

	/**
	 * Contains the description of an error in a Telegram Passport element;
	 * for bots only.
	**/
	public static final class InputPassportElementError extends Object {


		/**
		 * Type of Telegram Passport element that has the error.
		**/
		public PassportElementType type;

		/**
		 * Error message.
		**/
		public String message;

		/**
		 * Error source.
		**/
		public InputPassportElementErrorSource source;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 285756898;

		/**
		 * Contains the description of an error in a Telegram Passport element; for bots only.
		**/
		public InputPassportElementError() {}

		/**
		 * Contains the description of an error in a Telegram Passport element; for bots only.
		 *
		 * @param type Type of Telegram Passport element that has the error.
		 * @param message Error message.
		 * @param source Error source.
		**/
		public InputPassportElementError(PassportElementType type,
				String message,
				InputPassportElementErrorSource source) {
			this.type = type;
			this.message = message;
			this.source = source;
		}

		/**
		 * Contains the description of an error in a Telegram Passport element; for bots only.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputPassportElementError(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case PassportElementTypePersonalDetails.CONSTRUCTOR: this.type = new PassportElementTypePersonalDetails(input); break;
					case PassportElementTypePassport.CONSTRUCTOR: this.type = new PassportElementTypePassport(input); break;
					case PassportElementTypeDriverLicense.CONSTRUCTOR: this.type = new PassportElementTypeDriverLicense(input); break;
					case PassportElementTypeIdentityCard.CONSTRUCTOR: this.type = new PassportElementTypeIdentityCard(input); break;
					case PassportElementTypeInternalPassport.CONSTRUCTOR: this.type = new PassportElementTypeInternalPassport(input); break;
					case PassportElementTypeAddress.CONSTRUCTOR: this.type = new PassportElementTypeAddress(input); break;
					case PassportElementTypeUtilityBill.CONSTRUCTOR: this.type = new PassportElementTypeUtilityBill(input); break;
					case PassportElementTypeBankStatement.CONSTRUCTOR: this.type = new PassportElementTypeBankStatement(input); break;
					case PassportElementTypeRentalAgreement.CONSTRUCTOR: this.type = new PassportElementTypeRentalAgreement(input); break;
					case PassportElementTypePassportRegistration.CONSTRUCTOR: this.type = new PassportElementTypePassportRegistration(input); break;
					case PassportElementTypeTemporaryRegistration.CONSTRUCTOR: this.type = new PassportElementTypeTemporaryRegistration(input); break;
					case PassportElementTypePhoneNumber.CONSTRUCTOR: this.type = new PassportElementTypePhoneNumber(input); break;
					case PassportElementTypeEmailAddress.CONSTRUCTOR: this.type = new PassportElementTypeEmailAddress(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				byte[] messageTmp = new byte[input.readInt()];
				input.readFully(messageTmp);
				this.message = new String(messageTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputPassportElementErrorSourceUnspecified.CONSTRUCTOR: this.source = new InputPassportElementErrorSourceUnspecified(input); break;
					case InputPassportElementErrorSourceDataField.CONSTRUCTOR: this.source = new InputPassportElementErrorSourceDataField(input); break;
					case InputPassportElementErrorSourceFrontSide.CONSTRUCTOR: this.source = new InputPassportElementErrorSourceFrontSide(input); break;
					case InputPassportElementErrorSourceReverseSide.CONSTRUCTOR: this.source = new InputPassportElementErrorSourceReverseSide(input); break;
					case InputPassportElementErrorSourceSelfie.CONSTRUCTOR: this.source = new InputPassportElementErrorSourceSelfie(input); break;
					case InputPassportElementErrorSourceTranslationFile.CONSTRUCTOR: this.source = new InputPassportElementErrorSourceTranslationFile(input); break;
					case InputPassportElementErrorSourceTranslationFiles.CONSTRUCTOR: this.source = new InputPassportElementErrorSourceTranslationFiles(input); break;
					case InputPassportElementErrorSourceFile.CONSTRUCTOR: this.source = new InputPassportElementErrorSourceFile(input); break;
					case InputPassportElementErrorSourceFiles.CONSTRUCTOR: this.source = new InputPassportElementErrorSourceFiles(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputPassportElementError.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputPassportElementError.CONSTRUCTOR);
			if (this.type == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.type.serialize(output);
			}
			if (this.message == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] messageTmp = this.message.getBytes(StandardCharsets.UTF_8);
				output.writeInt(messageTmp.length);
				output.write(messageTmp);
			}
			if (this.source == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.source.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputPassportElementError inputPassportElementError = (InputPassportElementError) o;
			if (!Objects.equals(this.type, inputPassportElementError.type)) {
				return false;
			}
			if (this.message != inputPassportElementError.message) {
				return false;
			}
			if (!Objects.equals(this.source, inputPassportElementError.source)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.type == null ? 0 : this.type.hashCode();
			result = result * 31 + (this.message == null ? 0 : this.message.hashCode());
			result = result * 31 + (this.source == null ? 0 : this.source.hashCode());
			return result;
		}
	}

	/**
	 * The element contains an error in an unspecified place. The error will
	 * be considered resolved when new data is added.
	**/
	public static final class InputPassportElementErrorSourceUnspecified extends InputPassportElementErrorSource {


		/**
		 * Current hash of the entire element.
		**/
		public byte[] elementHash;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 267230319;

		/**
		 * The element contains an error in an unspecified place. The error will be considered resolved when new data is added.
		**/
		public InputPassportElementErrorSourceUnspecified() {}

		/**
		 * The element contains an error in an unspecified place. The error will be considered resolved when new data is added.
		 *
		 * @param elementHash Current hash of the entire element.
		**/
		public InputPassportElementErrorSourceUnspecified(byte[] elementHash) {
			this.elementHash = elementHash;
		}

		/**
		 * The element contains an error in an unspecified place. The error will be considered resolved when new data is added.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputPassportElementErrorSourceUnspecified(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.elementHash = new byte[input.readInt()];
				input.readFully(this.elementHash);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputPassportElementErrorSourceUnspecified.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputPassportElementErrorSourceUnspecified.CONSTRUCTOR);
			if (this.elementHash == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.elementHash.length);
				output.write(this.elementHash);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputPassportElementErrorSourceUnspecified inputPassportElementErrorSourceUnspecified = (InputPassportElementErrorSourceUnspecified) o;
			if (this.elementHash != inputPassportElementErrorSourceUnspecified.elementHash) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.elementHash);
		}
	}

	/**
	 * A data field contains an error. The error is considered resolved when
	 * the field&#039;s value changes.
	**/
	public static final class InputPassportElementErrorSourceDataField extends InputPassportElementErrorSource {


		/**
		 * Field name.
		**/
		public String fieldName;

		/**
		 * Current data hash.
		**/
		public byte[] dataHash;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -426795002;

		/**
		 * A data field contains an error. The error is considered resolved when the field&#039;s value changes.
		**/
		public InputPassportElementErrorSourceDataField() {}

		/**
		 * A data field contains an error. The error is considered resolved when the field&#039;s value changes.
		 *
		 * @param fieldName Field name.
		 * @param dataHash Current data hash.
		**/
		public InputPassportElementErrorSourceDataField(String fieldName, byte[] dataHash) {
			this.fieldName = fieldName;
			this.dataHash = dataHash;
		}

		/**
		 * A data field contains an error. The error is considered resolved when the field&#039;s value changes.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputPassportElementErrorSourceDataField(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] fieldNameTmp = new byte[input.readInt()];
				input.readFully(fieldNameTmp);
				this.fieldName = new String(fieldNameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				this.dataHash = new byte[input.readInt()];
				input.readFully(this.dataHash);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputPassportElementErrorSourceDataField.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputPassportElementErrorSourceDataField.CONSTRUCTOR);
			if (this.fieldName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] fieldNameTmp = this.fieldName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(fieldNameTmp.length);
				output.write(fieldNameTmp);
			}
			if (this.dataHash == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.dataHash.length);
				output.write(this.dataHash);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputPassportElementErrorSourceDataField inputPassportElementErrorSourceDataField = (InputPassportElementErrorSourceDataField) o;
			if (this.fieldName != inputPassportElementErrorSourceDataField.fieldName) {
				return false;
			}
			if (this.dataHash != inputPassportElementErrorSourceDataField.dataHash) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.fieldName == null ? 0 : this.fieldName.hashCode();
			result = result * 31 + (Arrays.hashCode(this.dataHash));
			return result;
		}
	}

	/**
	 * The front side of the document contains an error. The error is
	 * considered resolved when the file with the front side of the document
	 * changes.
	**/
	public static final class InputPassportElementErrorSourceFrontSide extends InputPassportElementErrorSource {


		/**
		 * Current hash of the file containing the front side.
		**/
		public byte[] fileHash;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 588023741;

		/**
		 * The front side of the document contains an error. The error is considered resolved when the file with the front side of the document changes.
		**/
		public InputPassportElementErrorSourceFrontSide() {}

		/**
		 * The front side of the document contains an error. The error is considered resolved when the file with the front side of the document changes.
		 *
		 * @param fileHash Current hash of the file containing the front side.
		**/
		public InputPassportElementErrorSourceFrontSide(byte[] fileHash) {
			this.fileHash = fileHash;
		}

		/**
		 * The front side of the document contains an error. The error is considered resolved when the file with the front side of the document changes.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputPassportElementErrorSourceFrontSide(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.fileHash = new byte[input.readInt()];
				input.readFully(this.fileHash);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputPassportElementErrorSourceFrontSide.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputPassportElementErrorSourceFrontSide.CONSTRUCTOR);
			if (this.fileHash == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.fileHash.length);
				output.write(this.fileHash);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputPassportElementErrorSourceFrontSide inputPassportElementErrorSourceFrontSide = (InputPassportElementErrorSourceFrontSide) o;
			if (this.fileHash != inputPassportElementErrorSourceFrontSide.fileHash) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.fileHash);
		}
	}

	/**
	 * The reverse side of the document contains an error. The error is
	 * considered resolved when the file with the reverse side of the
	 * document changes.
	**/
	public static final class InputPassportElementErrorSourceReverseSide extends InputPassportElementErrorSource {


		/**
		 * Current hash of the file containing the reverse side.
		**/
		public byte[] fileHash;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 413072891;

		/**
		 * The reverse side of the document contains an error. The error is considered resolved when the file with the reverse side of the document changes.
		**/
		public InputPassportElementErrorSourceReverseSide() {}

		/**
		 * The reverse side of the document contains an error. The error is considered resolved when the file with the reverse side of the document changes.
		 *
		 * @param fileHash Current hash of the file containing the reverse side.
		**/
		public InputPassportElementErrorSourceReverseSide(byte[] fileHash) {
			this.fileHash = fileHash;
		}

		/**
		 * The reverse side of the document contains an error. The error is considered resolved when the file with the reverse side of the document changes.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputPassportElementErrorSourceReverseSide(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.fileHash = new byte[input.readInt()];
				input.readFully(this.fileHash);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputPassportElementErrorSourceReverseSide.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputPassportElementErrorSourceReverseSide.CONSTRUCTOR);
			if (this.fileHash == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.fileHash.length);
				output.write(this.fileHash);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputPassportElementErrorSourceReverseSide inputPassportElementErrorSourceReverseSide = (InputPassportElementErrorSourceReverseSide) o;
			if (this.fileHash != inputPassportElementErrorSourceReverseSide.fileHash) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.fileHash);
		}
	}

	/**
	 * The selfie contains an error. The error is considered resolved when
	 * the file with the selfie changes.
	**/
	public static final class InputPassportElementErrorSourceSelfie extends InputPassportElementErrorSource {


		/**
		 * Current hash of the file containing the selfie.
		**/
		public byte[] fileHash;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -773575528;

		/**
		 * The selfie contains an error. The error is considered resolved when the file with the selfie changes.
		**/
		public InputPassportElementErrorSourceSelfie() {}

		/**
		 * The selfie contains an error. The error is considered resolved when the file with the selfie changes.
		 *
		 * @param fileHash Current hash of the file containing the selfie.
		**/
		public InputPassportElementErrorSourceSelfie(byte[] fileHash) {
			this.fileHash = fileHash;
		}

		/**
		 * The selfie contains an error. The error is considered resolved when the file with the selfie changes.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputPassportElementErrorSourceSelfie(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.fileHash = new byte[input.readInt()];
				input.readFully(this.fileHash);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputPassportElementErrorSourceSelfie.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputPassportElementErrorSourceSelfie.CONSTRUCTOR);
			if (this.fileHash == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.fileHash.length);
				output.write(this.fileHash);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputPassportElementErrorSourceSelfie inputPassportElementErrorSourceSelfie = (InputPassportElementErrorSourceSelfie) o;
			if (this.fileHash != inputPassportElementErrorSourceSelfie.fileHash) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.fileHash);
		}
	}

	/**
	 * One of the files containing the translation of the document contains
	 * an error. The error is considered resolved when the file with the
	 * translation changes.
	**/
	public static final class InputPassportElementErrorSourceTranslationFile extends InputPassportElementErrorSource {


		/**
		 * Current hash of the file containing the translation.
		**/
		public byte[] fileHash;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 505842299;

		/**
		 * One of the files containing the translation of the document contains an error. The error is considered resolved when the file with the translation changes.
		**/
		public InputPassportElementErrorSourceTranslationFile() {}

		/**
		 * One of the files containing the translation of the document contains an error. The error is considered resolved when the file with the translation changes.
		 *
		 * @param fileHash Current hash of the file containing the translation.
		**/
		public InputPassportElementErrorSourceTranslationFile(byte[] fileHash) {
			this.fileHash = fileHash;
		}

		/**
		 * One of the files containing the translation of the document contains an error. The error is considered resolved when the file with the translation changes.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputPassportElementErrorSourceTranslationFile(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.fileHash = new byte[input.readInt()];
				input.readFully(this.fileHash);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputPassportElementErrorSourceTranslationFile.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputPassportElementErrorSourceTranslationFile.CONSTRUCTOR);
			if (this.fileHash == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.fileHash.length);
				output.write(this.fileHash);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputPassportElementErrorSourceTranslationFile inputPassportElementErrorSourceTranslationFile = (InputPassportElementErrorSourceTranslationFile) o;
			if (this.fileHash != inputPassportElementErrorSourceTranslationFile.fileHash) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.fileHash);
		}
	}

	/**
	 * The translation of the document contains an error. The error is
	 * considered resolved when the list of files changes.
	**/
	public static final class InputPassportElementErrorSourceTranslationFiles extends InputPassportElementErrorSource {


		/**
		 * Current hashes of all files with the translation.
		**/
		public byte[][] fileHashes;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -527254048;

		/**
		 * The translation of the document contains an error. The error is considered resolved when the list of files changes.
		**/
		public InputPassportElementErrorSourceTranslationFiles() {}

		/**
		 * The translation of the document contains an error. The error is considered resolved when the list of files changes.
		 *
		 * @param fileHashes Current hashes of all files with the translation.
		**/
		public InputPassportElementErrorSourceTranslationFiles(byte[][] fileHashes) {
			this.fileHashes = fileHashes;
		}

		/**
		 * The translation of the document contains an error. The error is considered resolved when the list of files changes.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputPassportElementErrorSourceTranslationFiles(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.fileHashes = new byte[input.readInt()][];
				for (int i = 0; i < this.fileHashes.length; i++) {
					this.fileHashes[i] = new byte[input.readInt()];
					input.readFully(this.fileHashes[i]);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputPassportElementErrorSourceTranslationFiles.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputPassportElementErrorSourceTranslationFiles.CONSTRUCTOR);
			if (this.fileHashes == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.fileHashes.length);
				for (int i = 0; i < this.fileHashes.length; i++) {
					output.writeInt(this.fileHashes[i].length);
					output.write(this.fileHashes[i]);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputPassportElementErrorSourceTranslationFiles inputPassportElementErrorSourceTranslationFiles = (InputPassportElementErrorSourceTranslationFiles) o;
			if (!Arrays.deepEquals(this.fileHashes, inputPassportElementErrorSourceTranslationFiles.fileHashes)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.deepHashCode(this.fileHashes);
		}
	}

	/**
	 * The file contains an error. The error is considered resolved when the
	 * file changes.
	**/
	public static final class InputPassportElementErrorSourceFile extends InputPassportElementErrorSource {


		/**
		 * Current hash of the file which has the error.
		**/
		public byte[] fileHash;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -298492469;

		/**
		 * The file contains an error. The error is considered resolved when the file changes.
		**/
		public InputPassportElementErrorSourceFile() {}

		/**
		 * The file contains an error. The error is considered resolved when the file changes.
		 *
		 * @param fileHash Current hash of the file which has the error.
		**/
		public InputPassportElementErrorSourceFile(byte[] fileHash) {
			this.fileHash = fileHash;
		}

		/**
		 * The file contains an error. The error is considered resolved when the file changes.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputPassportElementErrorSourceFile(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.fileHash = new byte[input.readInt()];
				input.readFully(this.fileHash);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputPassportElementErrorSourceFile.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputPassportElementErrorSourceFile.CONSTRUCTOR);
			if (this.fileHash == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.fileHash.length);
				output.write(this.fileHash);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputPassportElementErrorSourceFile inputPassportElementErrorSourceFile = (InputPassportElementErrorSourceFile) o;
			if (this.fileHash != inputPassportElementErrorSourceFile.fileHash) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.fileHash);
		}
	}

	/**
	 * The list of attached files contains an error. The error is considered
	 * resolved when the file list changes.
	**/
	public static final class InputPassportElementErrorSourceFiles extends InputPassportElementErrorSource {


		/**
		 * Current hashes of all attached files.
		**/
		public byte[][] fileHashes;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2008541640;

		/**
		 * The list of attached files contains an error. The error is considered resolved when the file list changes.
		**/
		public InputPassportElementErrorSourceFiles() {}

		/**
		 * The list of attached files contains an error. The error is considered resolved when the file list changes.
		 *
		 * @param fileHashes Current hashes of all attached files.
		**/
		public InputPassportElementErrorSourceFiles(byte[][] fileHashes) {
			this.fileHashes = fileHashes;
		}

		/**
		 * The list of attached files contains an error. The error is considered resolved when the file list changes.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputPassportElementErrorSourceFiles(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.fileHashes = new byte[input.readInt()][];
				for (int i = 0; i < this.fileHashes.length; i++) {
					this.fileHashes[i] = new byte[input.readInt()];
					input.readFully(this.fileHashes[i]);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputPassportElementErrorSourceFiles.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputPassportElementErrorSourceFiles.CONSTRUCTOR);
			if (this.fileHashes == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.fileHashes.length);
				for (int i = 0; i < this.fileHashes.length; i++) {
					output.writeInt(this.fileHashes[i].length);
					output.write(this.fileHashes[i]);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputPassportElementErrorSourceFiles inputPassportElementErrorSourceFiles = (InputPassportElementErrorSourceFiles) o;
			if (!Arrays.deepEquals(this.fileHashes, inputPassportElementErrorSourceFiles.fileHashes)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.deepHashCode(this.fileHashes);
		}
	}

	/**
	 * A personal document to be saved to Telegram Passport.
	**/
	public static final class InputPersonalDocument extends Object {


		/**
		 * List of files containing the pages of the document.
		**/
		public InputFile[] files;

		/**
		 * List of files containing a certified English translation of the document.
		**/
		public InputFile[] translation;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1676966826;

		/**
		 * A personal document to be saved to Telegram Passport.
		**/
		public InputPersonalDocument() {}

		/**
		 * A personal document to be saved to Telegram Passport.
		 *
		 * @param files List of files containing the pages of the document.
		 * @param translation List of files containing a certified English translation of the document.
		**/
		public InputPersonalDocument(InputFile[] files, InputFile[] translation) {
			this.files = files;
			this.translation = translation;
		}

		/**
		 * A personal document to be saved to Telegram Passport.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputPersonalDocument(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.files = new InputFile[input.readInt()];
				for (int i = 0; i < this.files.length; i++) {
					switch(input.readInt()) {
						case InputFileId.CONSTRUCTOR: this.files[i] = new InputFileId(input); break;
						case InputFileRemote.CONSTRUCTOR: this.files[i] = new InputFileRemote(input); break;
						case InputFileLocal.CONSTRUCTOR: this.files[i] = new InputFileLocal(input); break;
						case InputFileGenerated.CONSTRUCTOR: this.files[i] = new InputFileGenerated(input); break;
						default: {
							throw new UnsupportedOperationException();
						}
					}
				}
			}
			if (input.readBoolean()) {
				this.translation = new InputFile[input.readInt()];
				for (int i = 0; i < this.translation.length; i++) {
					switch(input.readInt()) {
						case InputFileId.CONSTRUCTOR: this.translation[i] = new InputFileId(input); break;
						case InputFileRemote.CONSTRUCTOR: this.translation[i] = new InputFileRemote(input); break;
						case InputFileLocal.CONSTRUCTOR: this.translation[i] = new InputFileLocal(input); break;
						case InputFileGenerated.CONSTRUCTOR: this.translation[i] = new InputFileGenerated(input); break;
						default: {
							throw new UnsupportedOperationException();
						}
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputPersonalDocument.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputPersonalDocument.CONSTRUCTOR);
			if (this.files == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.files.length);
				for (int i = 0; i < this.files.length; i++) {
					this.files[i].serialize(output);
				}
			}
			if (this.translation == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.translation.length);
				for (int i = 0; i < this.translation.length; i++) {
					this.translation[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputPersonalDocument inputPersonalDocument = (InputPersonalDocument) o;
			if (!Arrays.equals(this.files, inputPersonalDocument.files)) {
				return false;
			}
			if (!Arrays.equals(this.translation, inputPersonalDocument.translation)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Arrays.hashCode(this.files);
			result = result * 31 + (Arrays.hashCode(this.translation));
			return result;
		}
	}

	/**
	 * A sticker to be added to a sticker set.
	**/
	public static final class InputSticker extends Object {


		/**
		 * File with the sticker; must fit in a 512x512 square. For WEBP stickers the file must be in WEBP or PNG format, which will be converted to WEBP server-side. See https://core.telegram.org/animated_stickers#technical-requirements for technical requirements.
		**/
		public InputFile sticker;

		/**
		 * String with 1-20 emoji corresponding to the sticker.
		**/
		public String emojis;

		/**
		 * Position where the mask is placed; pass null if not specified.
		**/
		public MaskPosition maskPosition;

		/**
		 * List of up to 20 keywords with total length up to 64 characters, which can be used to find the sticker.
		**/
		public String[] keywords;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 735226185;

		/**
		 * A sticker to be added to a sticker set.
		**/
		public InputSticker() {}

		/**
		 * A sticker to be added to a sticker set.
		 *
		 * @param sticker File with the sticker; must fit in a 512x512 square. For WEBP stickers the file must be in WEBP or PNG format, which will be converted to WEBP server-side. See https://core.telegram.org/animated_stickers#technical-requirements for technical requirements.
		 * @param emojis String with 1-20 emoji corresponding to the sticker.
		 * @param maskPosition Position where the mask is placed; pass null if not specified.
		 * @param keywords List of up to 20 keywords with total length up to 64 characters, which can be used to find the sticker.
		**/
		public InputSticker(InputFile sticker,
				String emojis,
				MaskPosition maskPosition,
				String[] keywords) {
			this.sticker = sticker;
			this.emojis = emojis;
			this.maskPosition = maskPosition;
			this.keywords = keywords;
		}

		/**
		 * A sticker to be added to a sticker set.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputSticker(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputFileId.CONSTRUCTOR: this.sticker = new InputFileId(input); break;
					case InputFileRemote.CONSTRUCTOR: this.sticker = new InputFileRemote(input); break;
					case InputFileLocal.CONSTRUCTOR: this.sticker = new InputFileLocal(input); break;
					case InputFileGenerated.CONSTRUCTOR: this.sticker = new InputFileGenerated(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				byte[] emojisTmp = new byte[input.readInt()];
				input.readFully(emojisTmp);
				this.emojis = new String(emojisTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (MaskPosition.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.maskPosition = new MaskPosition(input);
			}
			if (input.readBoolean()) {
				this.keywords = new String[input.readInt()];
				for (int i = 0; i < this.keywords.length; i++) {
					byte[] keywordsTmp = new byte[input.readInt()];
					input.readFully(keywordsTmp);
					this.keywords[i] = new String(keywordsTmp, StandardCharsets.UTF_8);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputSticker.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputSticker.CONSTRUCTOR);
			if (this.sticker == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.sticker.serialize(output);
			}
			if (this.emojis == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] emojisTmp = this.emojis.getBytes(StandardCharsets.UTF_8);
				output.writeInt(emojisTmp.length);
				output.write(emojisTmp);
			}
			if (this.maskPosition == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.maskPosition.serialize(output);
			}
			if (this.keywords == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.keywords.length);
				for (int i = 0; i < this.keywords.length; i++) {
					byte[] keywordsTmp = this.keywords[i].getBytes(StandardCharsets.UTF_8);
					output.writeInt(keywordsTmp.length);
					output.write(keywordsTmp);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputSticker inputSticker = (InputSticker) o;
			if (!Objects.equals(this.sticker, inputSticker.sticker)) {
				return false;
			}
			if (this.emojis != inputSticker.emojis) {
				return false;
			}
			if (!Objects.equals(this.maskPosition, inputSticker.maskPosition)) {
				return false;
			}
			if (!Arrays.equals(this.keywords, inputSticker.keywords)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.sticker == null ? 0 : this.sticker.hashCode();
			result = result * 31 + (this.emojis == null ? 0 : this.emojis.hashCode());
			result = result * 31 + (this.maskPosition == null ? 0 : this.maskPosition.hashCode());
			result = result * 31 + (Arrays.hashCode(this.keywords));
			return result;
		}
	}

	/**
	 * A thumbnail to be sent along with a file; must be in JPEG or WEBP
	 * format for stickers, and less than 200 KB in size.
	**/
	public static final class InputThumbnail extends Object {


		/**
		 * Thumbnail file to send. Sending thumbnails by fileId is currently not supported.
		**/
		public InputFile thumbnail;

		/**
		 * Thumbnail width, usually shouldn&#039;t exceed 320. Use 0 if unknown.
		**/
		public int width;

		/**
		 * Thumbnail height, usually shouldn&#039;t exceed 320. Use 0 if unknown.
		**/
		public int height;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1582387236;

		/**
		 * A thumbnail to be sent along with a file; must be in JPEG or WEBP format for stickers, and less than 200 KB in size.
		**/
		public InputThumbnail() {}

		/**
		 * A thumbnail to be sent along with a file; must be in JPEG or WEBP format for stickers, and less than 200 KB in size.
		 *
		 * @param thumbnail Thumbnail file to send. Sending thumbnails by fileId is currently not supported.
		 * @param width Thumbnail width, usually shouldn&#039;t exceed 320. Use 0 if unknown.
		 * @param height Thumbnail height, usually shouldn&#039;t exceed 320. Use 0 if unknown.
		**/
		public InputThumbnail(InputFile thumbnail, int width, int height) {
			this.thumbnail = thumbnail;
			this.width = width;
			this.height = height;
		}

		/**
		 * A thumbnail to be sent along with a file; must be in JPEG or WEBP format for stickers, and less than 200 KB in size.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InputThumbnail(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputFileId.CONSTRUCTOR: this.thumbnail = new InputFileId(input); break;
					case InputFileRemote.CONSTRUCTOR: this.thumbnail = new InputFileRemote(input); break;
					case InputFileLocal.CONSTRUCTOR: this.thumbnail = new InputFileLocal(input); break;
					case InputFileGenerated.CONSTRUCTOR: this.thumbnail = new InputFileGenerated(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.width = input.readInt();
			this.height = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InputThumbnail.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InputThumbnail.CONSTRUCTOR);
			if (this.thumbnail == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.thumbnail.serialize(output);
			}
			output.writeInt(this.width);
			output.writeInt(this.height);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InputThumbnail inputThumbnail = (InputThumbnail) o;
			if (!Objects.equals(this.thumbnail, inputThumbnail.thumbnail)) {
				return false;
			}
			if (this.width != inputThumbnail.width) {
				return false;
			}
			if (this.height != inputThumbnail.height) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.width);
			result = result * 31 + (this.thumbnail == null ? 0 : this.thumbnail.hashCode());
			return result;
		}
	}

	/**
	 * The link is a link to the active sessions section of the application.
	 * Use getActiveSessions to handle the link.
	**/
	public static final class InternalLinkTypeActiveSessions extends InternalLinkType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1886108589;

		/**
		 * The link is a link to the active sessions section of the application. Use getActiveSessions to handle the link.
		**/
		public InternalLinkTypeActiveSessions() {}

		/**
		 * The link is a link to the active sessions section of the application. Use getActiveSessions to handle the link.
		 *
		**/

		/**
		 * The link is a link to the active sessions section of the application. Use getActiveSessions to handle the link.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InternalLinkTypeActiveSessions(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InternalLinkTypeActiveSessions.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InternalLinkTypeActiveSessions.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return InternalLinkTypeActiveSessions.CONSTRUCTOR;
		}
	}

	/**
	 * The link is a link to an attachment menu bot to be opened in the
	 * specified or a chosen chat. Process given targetChat to open the
	 * chat. Then, call searchPublicChat with the given bot username, check
	 * that the user is a bot and can be added to attachment menu. Then, use
	 * getAttachmentMenuBot to receive information about the bot. If the bot
	 * isn&#039;t added to attachment menu, then user needs to confirm
	 * adding the bot to attachment menu. If user confirms adding, then use
	 * toggleBotIsAddedToAttachmentMenu to add it. If the attachment menu
	 * bot can&#039;t be used in the opened chat, show an error to the user.
	 * If the bot is added to attachment menu and can be used in the chat,
	 * then use openWebApp with the given URL.
	**/
	public static final class InternalLinkTypeAttachmentMenuBot extends InternalLinkType {


		/**
		 * Target chat to be opened.
		**/
		public TargetChat targetChat;

		/**
		 * Username of the bot.
		**/
		public String botUsername;

		/**
		 * URL to be passed to openWebApp.
		**/
		public String url;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1682719269;

		/**
		 * The link is a link to an attachment menu bot to be opened in the specified or a chosen chat. Process given targetChat to open the chat. Then, call searchPublicChat with the given bot username, check that the user is a bot and can be added to attachment menu. Then, use getAttachmentMenuBot to receive information about the bot. If the bot isn&#039;t added to attachment menu, then user needs to confirm adding the bot to attachment menu. If user confirms adding, then use toggleBotIsAddedToAttachmentMenu to add it. If the attachment menu bot can&#039;t be used in the opened chat, show an error to the user. If the bot is added to attachment menu and can be used in the chat, then use openWebApp with the given URL.
		**/
		public InternalLinkTypeAttachmentMenuBot() {}

		/**
		 * The link is a link to an attachment menu bot to be opened in the specified or a chosen chat. Process given targetChat to open the chat. Then, call searchPublicChat with the given bot username, check that the user is a bot and can be added to attachment menu. Then, use getAttachmentMenuBot to receive information about the bot. If the bot isn&#039;t added to attachment menu, then user needs to confirm adding the bot to attachment menu. If user confirms adding, then use toggleBotIsAddedToAttachmentMenu to add it. If the attachment menu bot can&#039;t be used in the opened chat, show an error to the user. If the bot is added to attachment menu and can be used in the chat, then use openWebApp with the given URL.
		 *
		 * @param targetChat Target chat to be opened.
		 * @param botUsername Username of the bot.
		 * @param url URL to be passed to openWebApp.
		**/
		public InternalLinkTypeAttachmentMenuBot(TargetChat targetChat, String botUsername, String url) {
			this.targetChat = targetChat;
			this.botUsername = botUsername;
			this.url = url;
		}

		/**
		 * The link is a link to an attachment menu bot to be opened in the specified or a chosen chat. Process given targetChat to open the chat. Then, call searchPublicChat with the given bot username, check that the user is a bot and can be added to attachment menu. Then, use getAttachmentMenuBot to receive information about the bot. If the bot isn&#039;t added to attachment menu, then user needs to confirm adding the bot to attachment menu. If user confirms adding, then use toggleBotIsAddedToAttachmentMenu to add it. If the attachment menu bot can&#039;t be used in the opened chat, show an error to the user. If the bot is added to attachment menu and can be used in the chat, then use openWebApp with the given URL.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InternalLinkTypeAttachmentMenuBot(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case TargetChatCurrent.CONSTRUCTOR: this.targetChat = new TargetChatCurrent(input); break;
					case TargetChatChosen.CONSTRUCTOR: this.targetChat = new TargetChatChosen(input); break;
					case TargetChatInternalLink.CONSTRUCTOR: this.targetChat = new TargetChatInternalLink(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				byte[] botUsernameTmp = new byte[input.readInt()];
				input.readFully(botUsernameTmp);
				this.botUsername = new String(botUsernameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] urlTmp = new byte[input.readInt()];
				input.readFully(urlTmp);
				this.url = new String(urlTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InternalLinkTypeAttachmentMenuBot.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InternalLinkTypeAttachmentMenuBot.CONSTRUCTOR);
			if (this.targetChat == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.targetChat.serialize(output);
			}
			if (this.botUsername == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] botUsernameTmp = this.botUsername.getBytes(StandardCharsets.UTF_8);
				output.writeInt(botUsernameTmp.length);
				output.write(botUsernameTmp);
			}
			if (this.url == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] urlTmp = this.url.getBytes(StandardCharsets.UTF_8);
				output.writeInt(urlTmp.length);
				output.write(urlTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InternalLinkTypeAttachmentMenuBot internalLinkTypeAttachmentMenuBot = (InternalLinkTypeAttachmentMenuBot) o;
			if (!Objects.equals(this.targetChat, internalLinkTypeAttachmentMenuBot.targetChat)) {
				return false;
			}
			if (this.botUsername != internalLinkTypeAttachmentMenuBot.botUsername) {
				return false;
			}
			if (this.url != internalLinkTypeAttachmentMenuBot.url) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.targetChat == null ? 0 : this.targetChat.hashCode();
			result = result * 31 + (this.botUsername == null ? 0 : this.botUsername.hashCode());
			result = result * 31 + (this.url == null ? 0 : this.url.hashCode());
			return result;
		}
	}

	/**
	 * The link contains an authentication code. Call
	 * checkAuthenticationCode with the code if the current authorization
	 * state is authorizationStateWaitCode.
	**/
	public static final class InternalLinkTypeAuthenticationCode extends InternalLinkType {


		/**
		 * The authentication code.
		**/
		public String code;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -209235982;

		/**
		 * The link contains an authentication code. Call checkAuthenticationCode with the code if the current authorization state is authorizationStateWaitCode.
		**/
		public InternalLinkTypeAuthenticationCode() {}

		/**
		 * The link contains an authentication code. Call checkAuthenticationCode with the code if the current authorization state is authorizationStateWaitCode.
		 *
		 * @param code The authentication code.
		**/
		public InternalLinkTypeAuthenticationCode(String code) {
			this.code = code;
		}

		/**
		 * The link contains an authentication code. Call checkAuthenticationCode with the code if the current authorization state is authorizationStateWaitCode.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InternalLinkTypeAuthenticationCode(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] codeTmp = new byte[input.readInt()];
				input.readFully(codeTmp);
				this.code = new String(codeTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InternalLinkTypeAuthenticationCode.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InternalLinkTypeAuthenticationCode.CONSTRUCTOR);
			if (this.code == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] codeTmp = this.code.getBytes(StandardCharsets.UTF_8);
				output.writeInt(codeTmp.length);
				output.write(codeTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InternalLinkTypeAuthenticationCode internalLinkTypeAuthenticationCode = (InternalLinkTypeAuthenticationCode) o;
			if (this.code != internalLinkTypeAuthenticationCode.code) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.code == null ? 0 : this.code.hashCode();
		}
	}

	/**
	 * The link is a link to a background. Call searchBackground with the
	 * given background name to process the link.
	**/
	public static final class InternalLinkTypeBackground extends InternalLinkType {


		/**
		 * Name of the background.
		**/
		public String backgroundName;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 185411848;

		/**
		 * The link is a link to a background. Call searchBackground with the given background name to process the link.
		**/
		public InternalLinkTypeBackground() {}

		/**
		 * The link is a link to a background. Call searchBackground with the given background name to process the link.
		 *
		 * @param backgroundName Name of the background.
		**/
		public InternalLinkTypeBackground(String backgroundName) {
			this.backgroundName = backgroundName;
		}

		/**
		 * The link is a link to a background. Call searchBackground with the given background name to process the link.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InternalLinkTypeBackground(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] backgroundNameTmp = new byte[input.readInt()];
				input.readFully(backgroundNameTmp);
				this.backgroundName = new String(backgroundNameTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InternalLinkTypeBackground.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InternalLinkTypeBackground.CONSTRUCTOR);
			if (this.backgroundName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] backgroundNameTmp = this.backgroundName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(backgroundNameTmp.length);
				output.write(backgroundNameTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InternalLinkTypeBackground internalLinkTypeBackground = (InternalLinkTypeBackground) o;
			if (this.backgroundName != internalLinkTypeBackground.backgroundName) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.backgroundName == null ? 0 : this.backgroundName.hashCode();
		}
	}

	/**
	 * The link is a link to a Telegram bot, which is supposed to be added
	 * to a channel chat as an administrator. Call searchPublicChat with the
	 * given bot username and check that the user is a bot, ask the current
	 * user to select a channel chat to add the bot to as an administrator.
	 * Then, call getChatMember to receive the current bot rights in the
	 * chat and if the bot already is an administrator, check that the
	 * current user can edit its administrator rights and combine received
	 * rights with the requested administrator rights. Then, show
	 * confirmation box to the user, and call setChatMemberStatus with the
	 * chosen chat and confirmed rights.
	**/
	public static final class InternalLinkTypeBotAddToChannel extends InternalLinkType {


		/**
		 * Username of the bot.
		**/
		public String botUsername;

		/**
		 * Expected administrator rights for the bot.
		**/
		public ChatAdministratorRights administratorRights;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1401602752;

		/**
		 * The link is a link to a Telegram bot, which is supposed to be added to a channel chat as an administrator. Call searchPublicChat with the given bot username and check that the user is a bot, ask the current user to select a channel chat to add the bot to as an administrator. Then, call getChatMember to receive the current bot rights in the chat and if the bot already is an administrator, check that the current user can edit its administrator rights and combine received rights with the requested administrator rights. Then, show confirmation box to the user, and call setChatMemberStatus with the chosen chat and confirmed rights.
		**/
		public InternalLinkTypeBotAddToChannel() {}

		/**
		 * The link is a link to a Telegram bot, which is supposed to be added to a channel chat as an administrator. Call searchPublicChat with the given bot username and check that the user is a bot, ask the current user to select a channel chat to add the bot to as an administrator. Then, call getChatMember to receive the current bot rights in the chat and if the bot already is an administrator, check that the current user can edit its administrator rights and combine received rights with the requested administrator rights. Then, show confirmation box to the user, and call setChatMemberStatus with the chosen chat and confirmed rights.
		 *
		 * @param botUsername Username of the bot.
		 * @param administratorRights Expected administrator rights for the bot.
		**/
		public InternalLinkTypeBotAddToChannel(String botUsername,
				ChatAdministratorRights administratorRights) {
			this.botUsername = botUsername;
			this.administratorRights = administratorRights;
		}

		/**
		 * The link is a link to a Telegram bot, which is supposed to be added to a channel chat as an administrator. Call searchPublicChat with the given bot username and check that the user is a bot, ask the current user to select a channel chat to add the bot to as an administrator. Then, call getChatMember to receive the current bot rights in the chat and if the bot already is an administrator, check that the current user can edit its administrator rights and combine received rights with the requested administrator rights. Then, show confirmation box to the user, and call setChatMemberStatus with the chosen chat and confirmed rights.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InternalLinkTypeBotAddToChannel(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] botUsernameTmp = new byte[input.readInt()];
				input.readFully(botUsernameTmp);
				this.botUsername = new String(botUsernameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (ChatAdministratorRights.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.administratorRights = new ChatAdministratorRights(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InternalLinkTypeBotAddToChannel.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InternalLinkTypeBotAddToChannel.CONSTRUCTOR);
			if (this.botUsername == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] botUsernameTmp = this.botUsername.getBytes(StandardCharsets.UTF_8);
				output.writeInt(botUsernameTmp.length);
				output.write(botUsernameTmp);
			}
			if (this.administratorRights == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.administratorRights.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InternalLinkTypeBotAddToChannel internalLinkTypeBotAddToChannel = (InternalLinkTypeBotAddToChannel) o;
			if (this.botUsername != internalLinkTypeBotAddToChannel.botUsername) {
				return false;
			}
			if (!Objects.equals(this.administratorRights, internalLinkTypeBotAddToChannel.administratorRights)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.botUsername == null ? 0 : this.botUsername.hashCode();
			result = result * 31 + (this.administratorRights == null ? 0 : this.administratorRights.hashCode());
			return result;
		}
	}

	/**
	 * The link is a link to a chat with a Telegram bot. Call
	 * searchPublicChat with the given bot username, check that the user is
	 * a bot, show START button in the chat with the bot, and then call
	 * sendBotStartMessage with the given start parameter after the button
	 * is pressed.
	**/
	public static final class InternalLinkTypeBotStart extends InternalLinkType {


		/**
		 * Username of the bot.
		**/
		public String botUsername;

		/**
		 * The parameter to be passed to sendBotStartMessage.
		**/
		public String startParameter;

		/**
		 * True, if sendBotStartMessage must be called automatically without showing the START button.
		**/
		public boolean autostart;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1066950637;

		/**
		 * The link is a link to a chat with a Telegram bot. Call searchPublicChat with the given bot username, check that the user is a bot, show START button in the chat with the bot, and then call sendBotStartMessage with the given start parameter after the button is pressed.
		**/
		public InternalLinkTypeBotStart() {}

		/**
		 * The link is a link to a chat with a Telegram bot. Call searchPublicChat with the given bot username, check that the user is a bot, show START button in the chat with the bot, and then call sendBotStartMessage with the given start parameter after the button is pressed.
		 *
		 * @param botUsername Username of the bot.
		 * @param startParameter The parameter to be passed to sendBotStartMessage.
		 * @param autostart True, if sendBotStartMessage must be called automatically without showing the START button.
		**/
		public InternalLinkTypeBotStart(String botUsername, String startParameter, boolean autostart) {
			this.botUsername = botUsername;
			this.startParameter = startParameter;
			this.autostart = autostart;
		}

		/**
		 * The link is a link to a chat with a Telegram bot. Call searchPublicChat with the given bot username, check that the user is a bot, show START button in the chat with the bot, and then call sendBotStartMessage with the given start parameter after the button is pressed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InternalLinkTypeBotStart(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] botUsernameTmp = new byte[input.readInt()];
				input.readFully(botUsernameTmp);
				this.botUsername = new String(botUsernameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] startParameterTmp = new byte[input.readInt()];
				input.readFully(startParameterTmp);
				this.startParameter = new String(startParameterTmp, StandardCharsets.UTF_8);
			}
			this.autostart = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InternalLinkTypeBotStart.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InternalLinkTypeBotStart.CONSTRUCTOR);
			if (this.botUsername == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] botUsernameTmp = this.botUsername.getBytes(StandardCharsets.UTF_8);
				output.writeInt(botUsernameTmp.length);
				output.write(botUsernameTmp);
			}
			if (this.startParameter == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] startParameterTmp = this.startParameter.getBytes(StandardCharsets.UTF_8);
				output.writeInt(startParameterTmp.length);
				output.write(startParameterTmp);
			}
			output.writeBoolean(this.autostart);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InternalLinkTypeBotStart internalLinkTypeBotStart = (InternalLinkTypeBotStart) o;
			if (this.botUsername != internalLinkTypeBotStart.botUsername) {
				return false;
			}
			if (this.startParameter != internalLinkTypeBotStart.startParameter) {
				return false;
			}
			if (this.autostart != internalLinkTypeBotStart.autostart) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.autostart);
			result = result * 31 + (this.botUsername == null ? 0 : this.botUsername.hashCode());
			result = result * 31 + (this.startParameter == null ? 0 : this.startParameter.hashCode());
			return result;
		}
	}

	/**
	 * The link is a link to a Telegram bot, which is supposed to be added
	 * to a group chat. Call searchPublicChat with the given bot username,
	 * check that the user is a bot and can be added to groups, ask the
	 * current user to select a basic group or a supergroup chat to add the
	 * bot to, taking into account that bots can be added to a public
	 * supergroup only by administrators of the supergroup. If administrator
	 * rights are provided by the link, call getChatMember to receive the
	 * current bot rights in the chat and if the bot already is an
	 * administrator, check that the current user can edit its administrator
	 * rights, combine received rights with the requested administrator
	 * rights, show confirmation box to the user, and call
	 * setChatMemberStatus with the chosen chat and confirmed administrator
	 * rights. Before call to setChatMemberStatus it may be required to
	 * upgrade the chosen basic group chat to a supergroup chat. Then, if
	 * startParameter isn&#039;t empty, call sendBotStartMessage with the
	 * given start parameter and the chosen chat; otherwise, just send
	 * /start message with bot&#039;s username added to the chat.
	**/
	public static final class InternalLinkTypeBotStartInGroup extends InternalLinkType {


		/**
		 * Username of the bot.
		**/
		public String botUsername;

		/**
		 * The parameter to be passed to sendBotStartMessage.
		**/
		public String startParameter;

		/**
		 * Expected administrator rights for the bot; may be null.
		**/
		public ChatAdministratorRights administratorRights;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -905081650;

		/**
		 * The link is a link to a Telegram bot, which is supposed to be added to a group chat. Call searchPublicChat with the given bot username, check that the user is a bot and can be added to groups, ask the current user to select a basic group or a supergroup chat to add the bot to, taking into account that bots can be added to a public supergroup only by administrators of the supergroup. If administrator rights are provided by the link, call getChatMember to receive the current bot rights in the chat and if the bot already is an administrator, check that the current user can edit its administrator rights, combine received rights with the requested administrator rights, show confirmation box to the user, and call setChatMemberStatus with the chosen chat and confirmed administrator rights. Before call to setChatMemberStatus it may be required to upgrade the chosen basic group chat to a supergroup chat. Then, if startParameter isn&#039;t empty, call sendBotStartMessage with the given start parameter and the chosen chat; otherwise, just send /start message with bot&#039;s username added to the chat.
		**/
		public InternalLinkTypeBotStartInGroup() {}

		/**
		 * The link is a link to a Telegram bot, which is supposed to be added to a group chat. Call searchPublicChat with the given bot username, check that the user is a bot and can be added to groups, ask the current user to select a basic group or a supergroup chat to add the bot to, taking into account that bots can be added to a public supergroup only by administrators of the supergroup. If administrator rights are provided by the link, call getChatMember to receive the current bot rights in the chat and if the bot already is an administrator, check that the current user can edit its administrator rights, combine received rights with the requested administrator rights, show confirmation box to the user, and call setChatMemberStatus with the chosen chat and confirmed administrator rights. Before call to setChatMemberStatus it may be required to upgrade the chosen basic group chat to a supergroup chat. Then, if startParameter isn&#039;t empty, call sendBotStartMessage with the given start parameter and the chosen chat; otherwise, just send /start message with bot&#039;s username added to the chat.
		 *
		 * @param botUsername Username of the bot.
		 * @param startParameter The parameter to be passed to sendBotStartMessage.
		 * @param administratorRights Expected administrator rights for the bot; may be null.
		**/
		public InternalLinkTypeBotStartInGroup(String botUsername,
				String startParameter,
				ChatAdministratorRights administratorRights) {
			this.botUsername = botUsername;
			this.startParameter = startParameter;
			this.administratorRights = administratorRights;
		}

		/**
		 * The link is a link to a Telegram bot, which is supposed to be added to a group chat. Call searchPublicChat with the given bot username, check that the user is a bot and can be added to groups, ask the current user to select a basic group or a supergroup chat to add the bot to, taking into account that bots can be added to a public supergroup only by administrators of the supergroup. If administrator rights are provided by the link, call getChatMember to receive the current bot rights in the chat and if the bot already is an administrator, check that the current user can edit its administrator rights, combine received rights with the requested administrator rights, show confirmation box to the user, and call setChatMemberStatus with the chosen chat and confirmed administrator rights. Before call to setChatMemberStatus it may be required to upgrade the chosen basic group chat to a supergroup chat. Then, if startParameter isn&#039;t empty, call sendBotStartMessage with the given start parameter and the chosen chat; otherwise, just send /start message with bot&#039;s username added to the chat.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InternalLinkTypeBotStartInGroup(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] botUsernameTmp = new byte[input.readInt()];
				input.readFully(botUsernameTmp);
				this.botUsername = new String(botUsernameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] startParameterTmp = new byte[input.readInt()];
				input.readFully(startParameterTmp);
				this.startParameter = new String(startParameterTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (ChatAdministratorRights.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.administratorRights = new ChatAdministratorRights(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InternalLinkTypeBotStartInGroup.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InternalLinkTypeBotStartInGroup.CONSTRUCTOR);
			if (this.botUsername == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] botUsernameTmp = this.botUsername.getBytes(StandardCharsets.UTF_8);
				output.writeInt(botUsernameTmp.length);
				output.write(botUsernameTmp);
			}
			if (this.startParameter == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] startParameterTmp = this.startParameter.getBytes(StandardCharsets.UTF_8);
				output.writeInt(startParameterTmp.length);
				output.write(startParameterTmp);
			}
			if (this.administratorRights == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.administratorRights.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InternalLinkTypeBotStartInGroup internalLinkTypeBotStartInGroup = (InternalLinkTypeBotStartInGroup) o;
			if (this.botUsername != internalLinkTypeBotStartInGroup.botUsername) {
				return false;
			}
			if (this.startParameter != internalLinkTypeBotStartInGroup.startParameter) {
				return false;
			}
			if (!Objects.equals(this.administratorRights, internalLinkTypeBotStartInGroup.administratorRights)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.botUsername == null ? 0 : this.botUsername.hashCode();
			result = result * 31 + (this.startParameter == null ? 0 : this.startParameter.hashCode());
			result = result * 31 + (this.administratorRights == null ? 0 : this.administratorRights.hashCode());
			return result;
		}
	}

	/**
	 * The link is a link to the change phone number section of the app.
	**/
	public static final class InternalLinkTypeChangePhoneNumber extends InternalLinkType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -265856255;

		/**
		 * The link is a link to the change phone number section of the app.
		**/
		public InternalLinkTypeChangePhoneNumber() {}

		/**
		 * The link is a link to the change phone number section of the app.
		 *
		**/

		/**
		 * The link is a link to the change phone number section of the app.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InternalLinkTypeChangePhoneNumber(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InternalLinkTypeChangePhoneNumber.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InternalLinkTypeChangePhoneNumber.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return InternalLinkTypeChangePhoneNumber.CONSTRUCTOR;
		}
	}

	/**
	 * The link is an invite link to a chat folder. Call
	 * checkChatFolderInviteLink with the given invite link to process the
	 * link.
	**/
	public static final class InternalLinkTypeChatFolderInvite extends InternalLinkType {


		/**
		 * Internal representation of the invite link.
		**/
		public String inviteLink;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1984804546;

		/**
		 * The link is an invite link to a chat folder. Call checkChatFolderInviteLink with the given invite link to process the link.
		**/
		public InternalLinkTypeChatFolderInvite() {}

		/**
		 * The link is an invite link to a chat folder. Call checkChatFolderInviteLink with the given invite link to process the link.
		 *
		 * @param inviteLink Internal representation of the invite link.
		**/
		public InternalLinkTypeChatFolderInvite(String inviteLink) {
			this.inviteLink = inviteLink;
		}

		/**
		 * The link is an invite link to a chat folder. Call checkChatFolderInviteLink with the given invite link to process the link.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InternalLinkTypeChatFolderInvite(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] inviteLinkTmp = new byte[input.readInt()];
				input.readFully(inviteLinkTmp);
				this.inviteLink = new String(inviteLinkTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InternalLinkTypeChatFolderInvite.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InternalLinkTypeChatFolderInvite.CONSTRUCTOR);
			if (this.inviteLink == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] inviteLinkTmp = this.inviteLink.getBytes(StandardCharsets.UTF_8);
				output.writeInt(inviteLinkTmp.length);
				output.write(inviteLinkTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InternalLinkTypeChatFolderInvite internalLinkTypeChatFolderInvite = (InternalLinkTypeChatFolderInvite) o;
			if (this.inviteLink != internalLinkTypeChatFolderInvite.inviteLink) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.inviteLink == null ? 0 : this.inviteLink.hashCode();
		}
	}

	/**
	 * The link is a link to the folder section of the app settings.
	**/
	public static final class InternalLinkTypeChatFolderSettings extends InternalLinkType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1073805988;

		/**
		 * The link is a link to the folder section of the app settings.
		**/
		public InternalLinkTypeChatFolderSettings() {}

		/**
		 * The link is a link to the folder section of the app settings.
		 *
		**/

		/**
		 * The link is a link to the folder section of the app settings.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InternalLinkTypeChatFolderSettings(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InternalLinkTypeChatFolderSettings.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InternalLinkTypeChatFolderSettings.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return InternalLinkTypeChatFolderSettings.CONSTRUCTOR;
		}
	}

	/**
	 * The link is a chat invite link. Call checkChatInviteLink with the
	 * given invite link to process the link.
	**/
	public static final class InternalLinkTypeChatInvite extends InternalLinkType {


		/**
		 * Internal representation of the invite link.
		**/
		public String inviteLink;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 428621017;

		/**
		 * The link is a chat invite link. Call checkChatInviteLink with the given invite link to process the link.
		**/
		public InternalLinkTypeChatInvite() {}

		/**
		 * The link is a chat invite link. Call checkChatInviteLink with the given invite link to process the link.
		 *
		 * @param inviteLink Internal representation of the invite link.
		**/
		public InternalLinkTypeChatInvite(String inviteLink) {
			this.inviteLink = inviteLink;
		}

		/**
		 * The link is a chat invite link. Call checkChatInviteLink with the given invite link to process the link.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InternalLinkTypeChatInvite(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] inviteLinkTmp = new byte[input.readInt()];
				input.readFully(inviteLinkTmp);
				this.inviteLink = new String(inviteLinkTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InternalLinkTypeChatInvite.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InternalLinkTypeChatInvite.CONSTRUCTOR);
			if (this.inviteLink == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] inviteLinkTmp = this.inviteLink.getBytes(StandardCharsets.UTF_8);
				output.writeInt(inviteLinkTmp.length);
				output.write(inviteLinkTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InternalLinkTypeChatInvite internalLinkTypeChatInvite = (InternalLinkTypeChatInvite) o;
			if (this.inviteLink != internalLinkTypeChatInvite.inviteLink) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.inviteLink == null ? 0 : this.inviteLink.hashCode();
		}
	}

	/**
	 * The link is a link to the default message auto-delete timer settings
	 * section of the app settings.
	**/
	public static final class InternalLinkTypeDefaultMessageAutoDeleteTimerSettings extends InternalLinkType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 732625201;

		/**
		 * The link is a link to the default message auto-delete timer settings section of the app settings.
		**/
		public InternalLinkTypeDefaultMessageAutoDeleteTimerSettings() {}

		/**
		 * The link is a link to the default message auto-delete timer settings section of the app settings.
		 *
		**/

		/**
		 * The link is a link to the default message auto-delete timer settings section of the app settings.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InternalLinkTypeDefaultMessageAutoDeleteTimerSettings(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InternalLinkTypeDefaultMessageAutoDeleteTimerSettings.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InternalLinkTypeDefaultMessageAutoDeleteTimerSettings.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return InternalLinkTypeDefaultMessageAutoDeleteTimerSettings.CONSTRUCTOR;
		}
	}

	/**
	 * The link is a link to the edit profile section of the app settings.
	**/
	public static final class InternalLinkTypeEditProfileSettings extends InternalLinkType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1022472090;

		/**
		 * The link is a link to the edit profile section of the app settings.
		**/
		public InternalLinkTypeEditProfileSettings() {}

		/**
		 * The link is a link to the edit profile section of the app settings.
		 *
		**/

		/**
		 * The link is a link to the edit profile section of the app settings.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InternalLinkTypeEditProfileSettings(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InternalLinkTypeEditProfileSettings.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InternalLinkTypeEditProfileSettings.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return InternalLinkTypeEditProfileSettings.CONSTRUCTOR;
		}
	}

	/**
	 * The link is a link to a game. Call searchPublicChat with the given
	 * bot username, check that the user is a bot, ask the current user to
	 * select a chat to send the game, and then call sendMessage with
	 * inputMessageGame.
	**/
	public static final class InternalLinkTypeGame extends InternalLinkType {


		/**
		 * Username of the bot that owns the game.
		**/
		public String botUsername;

		/**
		 * Short name of the game.
		**/
		public String gameShortName;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -260788787;

		/**
		 * The link is a link to a game. Call searchPublicChat with the given bot username, check that the user is a bot, ask the current user to select a chat to send the game, and then call sendMessage with inputMessageGame.
		**/
		public InternalLinkTypeGame() {}

		/**
		 * The link is a link to a game. Call searchPublicChat with the given bot username, check that the user is a bot, ask the current user to select a chat to send the game, and then call sendMessage with inputMessageGame.
		 *
		 * @param botUsername Username of the bot that owns the game.
		 * @param gameShortName Short name of the game.
		**/
		public InternalLinkTypeGame(String botUsername, String gameShortName) {
			this.botUsername = botUsername;
			this.gameShortName = gameShortName;
		}

		/**
		 * The link is a link to a game. Call searchPublicChat with the given bot username, check that the user is a bot, ask the current user to select a chat to send the game, and then call sendMessage with inputMessageGame.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InternalLinkTypeGame(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] botUsernameTmp = new byte[input.readInt()];
				input.readFully(botUsernameTmp);
				this.botUsername = new String(botUsernameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] gameShortNameTmp = new byte[input.readInt()];
				input.readFully(gameShortNameTmp);
				this.gameShortName = new String(gameShortNameTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InternalLinkTypeGame.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InternalLinkTypeGame.CONSTRUCTOR);
			if (this.botUsername == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] botUsernameTmp = this.botUsername.getBytes(StandardCharsets.UTF_8);
				output.writeInt(botUsernameTmp.length);
				output.write(botUsernameTmp);
			}
			if (this.gameShortName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] gameShortNameTmp = this.gameShortName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(gameShortNameTmp.length);
				output.write(gameShortNameTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InternalLinkTypeGame internalLinkTypeGame = (InternalLinkTypeGame) o;
			if (this.botUsername != internalLinkTypeGame.botUsername) {
				return false;
			}
			if (this.gameShortName != internalLinkTypeGame.gameShortName) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.botUsername == null ? 0 : this.botUsername.hashCode();
			result = result * 31 + (this.gameShortName == null ? 0 : this.gameShortName.hashCode());
			return result;
		}
	}

	/**
	 * The link must be opened in an Instant View. Call
	 * getWebPageInstantView with the given URL to process the link.
	**/
	public static final class InternalLinkTypeInstantView extends InternalLinkType {


		/**
		 * URL to be passed to getWebPageInstantView.
		**/
		public String url;

		/**
		 * An URL to open if getWebPageInstantView fails.
		**/
		public String fallbackUrl;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1776607039;

		/**
		 * The link must be opened in an Instant View. Call getWebPageInstantView with the given URL to process the link.
		**/
		public InternalLinkTypeInstantView() {}

		/**
		 * The link must be opened in an Instant View. Call getWebPageInstantView with the given URL to process the link.
		 *
		 * @param url URL to be passed to getWebPageInstantView.
		 * @param fallbackUrl An URL to open if getWebPageInstantView fails.
		**/
		public InternalLinkTypeInstantView(String url, String fallbackUrl) {
			this.url = url;
			this.fallbackUrl = fallbackUrl;
		}

		/**
		 * The link must be opened in an Instant View. Call getWebPageInstantView with the given URL to process the link.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InternalLinkTypeInstantView(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] urlTmp = new byte[input.readInt()];
				input.readFully(urlTmp);
				this.url = new String(urlTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] fallbackUrlTmp = new byte[input.readInt()];
				input.readFully(fallbackUrlTmp);
				this.fallbackUrl = new String(fallbackUrlTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InternalLinkTypeInstantView.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InternalLinkTypeInstantView.CONSTRUCTOR);
			if (this.url == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] urlTmp = this.url.getBytes(StandardCharsets.UTF_8);
				output.writeInt(urlTmp.length);
				output.write(urlTmp);
			}
			if (this.fallbackUrl == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] fallbackUrlTmp = this.fallbackUrl.getBytes(StandardCharsets.UTF_8);
				output.writeInt(fallbackUrlTmp.length);
				output.write(fallbackUrlTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InternalLinkTypeInstantView internalLinkTypeInstantView = (InternalLinkTypeInstantView) o;
			if (this.url != internalLinkTypeInstantView.url) {
				return false;
			}
			if (this.fallbackUrl != internalLinkTypeInstantView.fallbackUrl) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.url == null ? 0 : this.url.hashCode();
			result = result * 31 + (this.fallbackUrl == null ? 0 : this.fallbackUrl.hashCode());
			return result;
		}
	}

	/**
	 * The link is a link to an invoice. Call getPaymentForm with the given
	 * invoice name to process the link.
	**/
	public static final class InternalLinkTypeInvoice extends InternalLinkType {


		/**
		 * Name of the invoice.
		**/
		public String invoiceName;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -213094996;

		/**
		 * The link is a link to an invoice. Call getPaymentForm with the given invoice name to process the link.
		**/
		public InternalLinkTypeInvoice() {}

		/**
		 * The link is a link to an invoice. Call getPaymentForm with the given invoice name to process the link.
		 *
		 * @param invoiceName Name of the invoice.
		**/
		public InternalLinkTypeInvoice(String invoiceName) {
			this.invoiceName = invoiceName;
		}

		/**
		 * The link is a link to an invoice. Call getPaymentForm with the given invoice name to process the link.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InternalLinkTypeInvoice(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] invoiceNameTmp = new byte[input.readInt()];
				input.readFully(invoiceNameTmp);
				this.invoiceName = new String(invoiceNameTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InternalLinkTypeInvoice.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InternalLinkTypeInvoice.CONSTRUCTOR);
			if (this.invoiceName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] invoiceNameTmp = this.invoiceName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(invoiceNameTmp.length);
				output.write(invoiceNameTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InternalLinkTypeInvoice internalLinkTypeInvoice = (InternalLinkTypeInvoice) o;
			if (this.invoiceName != internalLinkTypeInvoice.invoiceName) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.invoiceName == null ? 0 : this.invoiceName.hashCode();
		}
	}

	/**
	 * The link is a link to a language pack. Call getLanguagePackInfo with
	 * the given language pack identifier to process the link.
	**/
	public static final class InternalLinkTypeLanguagePack extends InternalLinkType {


		/**
		 * Language pack identifier.
		**/
		public String languagePackId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1450766996;

		/**
		 * The link is a link to a language pack. Call getLanguagePackInfo with the given language pack identifier to process the link.
		**/
		public InternalLinkTypeLanguagePack() {}

		/**
		 * The link is a link to a language pack. Call getLanguagePackInfo with the given language pack identifier to process the link.
		 *
		 * @param languagePackId Language pack identifier.
		**/
		public InternalLinkTypeLanguagePack(String languagePackId) {
			this.languagePackId = languagePackId;
		}

		/**
		 * The link is a link to a language pack. Call getLanguagePackInfo with the given language pack identifier to process the link.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InternalLinkTypeLanguagePack(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] languagePackIdTmp = new byte[input.readInt()];
				input.readFully(languagePackIdTmp);
				this.languagePackId = new String(languagePackIdTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InternalLinkTypeLanguagePack.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InternalLinkTypeLanguagePack.CONSTRUCTOR);
			if (this.languagePackId == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] languagePackIdTmp = this.languagePackId.getBytes(StandardCharsets.UTF_8);
				output.writeInt(languagePackIdTmp.length);
				output.write(languagePackIdTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InternalLinkTypeLanguagePack internalLinkTypeLanguagePack = (InternalLinkTypeLanguagePack) o;
			if (this.languagePackId != internalLinkTypeLanguagePack.languagePackId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.languagePackId == null ? 0 : this.languagePackId.hashCode();
		}
	}

	/**
	 * The link is a link to the language section of the app settings.
	**/
	public static final class InternalLinkTypeLanguageSettings extends InternalLinkType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1340479770;

		/**
		 * The link is a link to the language section of the app settings.
		**/
		public InternalLinkTypeLanguageSettings() {}

		/**
		 * The link is a link to the language section of the app settings.
		 *
		**/

		/**
		 * The link is a link to the language section of the app settings.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InternalLinkTypeLanguageSettings(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InternalLinkTypeLanguageSettings.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InternalLinkTypeLanguageSettings.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return InternalLinkTypeLanguageSettings.CONSTRUCTOR;
		}
	}

	/**
	 * The link is a link to a Telegram message or a forum topic. Call
	 * getMessageLinkInfo with the given URL to process the link.
	**/
	public static final class InternalLinkTypeMessage extends InternalLinkType {


		/**
		 * URL to be passed to getMessageLinkInfo.
		**/
		public String url;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 978541650;

		/**
		 * The link is a link to a Telegram message or a forum topic. Call getMessageLinkInfo with the given URL to process the link.
		**/
		public InternalLinkTypeMessage() {}

		/**
		 * The link is a link to a Telegram message or a forum topic. Call getMessageLinkInfo with the given URL to process the link.
		 *
		 * @param url URL to be passed to getMessageLinkInfo.
		**/
		public InternalLinkTypeMessage(String url) {
			this.url = url;
		}

		/**
		 * The link is a link to a Telegram message or a forum topic. Call getMessageLinkInfo with the given URL to process the link.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InternalLinkTypeMessage(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] urlTmp = new byte[input.readInt()];
				input.readFully(urlTmp);
				this.url = new String(urlTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InternalLinkTypeMessage.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InternalLinkTypeMessage.CONSTRUCTOR);
			if (this.url == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] urlTmp = this.url.getBytes(StandardCharsets.UTF_8);
				output.writeInt(urlTmp.length);
				output.write(urlTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InternalLinkTypeMessage internalLinkTypeMessage = (InternalLinkTypeMessage) o;
			if (this.url != internalLinkTypeMessage.url) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.url == null ? 0 : this.url.hashCode();
		}
	}

	/**
	 * The link contains a message draft text. A share screen needs to be
	 * shown to the user, then the chosen chat must be opened and the text
	 * is added to the input field.
	**/
	public static final class InternalLinkTypeMessageDraft extends InternalLinkType {


		/**
		 * Message draft text.
		**/
		public FormattedText text;

		/**
		 * True, if the first line of the text contains a link. If true, the input field needs to be focused and the text after the link must be selected.
		**/
		public boolean containsLink;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 661633749;

		/**
		 * The link contains a message draft text. A share screen needs to be shown to the user, then the chosen chat must be opened and the text is added to the input field.
		**/
		public InternalLinkTypeMessageDraft() {}

		/**
		 * The link contains a message draft text. A share screen needs to be shown to the user, then the chosen chat must be opened and the text is added to the input field.
		 *
		 * @param text Message draft text.
		 * @param containsLink True, if the first line of the text contains a link. If true, the input field needs to be focused and the text after the link must be selected.
		**/
		public InternalLinkTypeMessageDraft(FormattedText text, boolean containsLink) {
			this.text = text;
			this.containsLink = containsLink;
		}

		/**
		 * The link contains a message draft text. A share screen needs to be shown to the user, then the chosen chat must be opened and the text is added to the input field.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InternalLinkTypeMessageDraft(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (FormattedText.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.text = new FormattedText(input);
			}
			this.containsLink = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InternalLinkTypeMessageDraft.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InternalLinkTypeMessageDraft.CONSTRUCTOR);
			if (this.text == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.text.serialize(output);
			}
			output.writeBoolean(this.containsLink);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InternalLinkTypeMessageDraft internalLinkTypeMessageDraft = (InternalLinkTypeMessageDraft) o;
			if (!Objects.equals(this.text, internalLinkTypeMessageDraft.text)) {
				return false;
			}
			if (this.containsLink != internalLinkTypeMessageDraft.containsLink) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.containsLink);
			result = result * 31 + (this.text == null ? 0 : this.text.hashCode());
			return result;
		}
	}

	/**
	 * The link contains a request of Telegram passport data. Call
	 * getPassportAuthorizationForm with the given parameters to process the
	 * link if the link was received from outside of the application;
	 * otherwise, ignore it.
	**/
	public static final class InternalLinkTypePassportDataRequest extends InternalLinkType {


		/**
		 * User identifier of the service&#039;s bot.
		**/
		public long botUserId;

		/**
		 * Telegram Passport element types requested by the service.
		**/
		public String scope;

		/**
		 * Service&#039;s public key.
		**/
		public String publicKey;

		/**
		 * Unique request identifier provided by the service.
		**/
		public String nonce;

		/**
		 * An HTTP URL to open once the request is finished, canceled, or failed with the parameters tgPassport=success, tgPassport=cancel, or tgPassport=error&amp;error=... respectively. If empty, then onActivityResult method must be used to return response on Android, or the link tgbot{botUserId}://passport/success or tgbot{botUserId}://passport/cancel must be opened otherwise.
		**/
		public String callbackUrl;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -988819839;

		/**
		 * The link contains a request of Telegram passport data. Call getPassportAuthorizationForm with the given parameters to process the link if the link was received from outside of the application; otherwise, ignore it.
		**/
		public InternalLinkTypePassportDataRequest() {}

		/**
		 * The link contains a request of Telegram passport data. Call getPassportAuthorizationForm with the given parameters to process the link if the link was received from outside of the application; otherwise, ignore it.
		 *
		 * @param botUserId User identifier of the service&#039;s bot.
		 * @param scope Telegram Passport element types requested by the service.
		 * @param publicKey Service&#039;s public key.
		 * @param nonce Unique request identifier provided by the service.
		 * @param callbackUrl An HTTP URL to open once the request is finished, canceled, or failed with the parameters tgPassport=success, tgPassport=cancel, or tgPassport=error&amp;error=... respectively. If empty, then onActivityResult method must be used to return response on Android, or the link tgbot{botUserId}://passport/success or tgbot{botUserId}://passport/cancel must be opened otherwise.
		**/
		public InternalLinkTypePassportDataRequest(long botUserId,
				String scope,
				String publicKey,
				String nonce,
				String callbackUrl) {
			this.botUserId = botUserId;
			this.scope = scope;
			this.publicKey = publicKey;
			this.nonce = nonce;
			this.callbackUrl = callbackUrl;
		}

		/**
		 * The link contains a request of Telegram passport data. Call getPassportAuthorizationForm with the given parameters to process the link if the link was received from outside of the application; otherwise, ignore it.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InternalLinkTypePassportDataRequest(DataInput input) throws IOException {
			this.botUserId = input.readLong();
			if (input.readBoolean()) {
				byte[] scopeTmp = new byte[input.readInt()];
				input.readFully(scopeTmp);
				this.scope = new String(scopeTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] publicKeyTmp = new byte[input.readInt()];
				input.readFully(publicKeyTmp);
				this.publicKey = new String(publicKeyTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] nonceTmp = new byte[input.readInt()];
				input.readFully(nonceTmp);
				this.nonce = new String(nonceTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] callbackUrlTmp = new byte[input.readInt()];
				input.readFully(callbackUrlTmp);
				this.callbackUrl = new String(callbackUrlTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InternalLinkTypePassportDataRequest.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InternalLinkTypePassportDataRequest.CONSTRUCTOR);
			output.writeLong(this.botUserId);
			if (this.scope == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] scopeTmp = this.scope.getBytes(StandardCharsets.UTF_8);
				output.writeInt(scopeTmp.length);
				output.write(scopeTmp);
			}
			if (this.publicKey == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] publicKeyTmp = this.publicKey.getBytes(StandardCharsets.UTF_8);
				output.writeInt(publicKeyTmp.length);
				output.write(publicKeyTmp);
			}
			if (this.nonce == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nonceTmp = this.nonce.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nonceTmp.length);
				output.write(nonceTmp);
			}
			if (this.callbackUrl == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] callbackUrlTmp = this.callbackUrl.getBytes(StandardCharsets.UTF_8);
				output.writeInt(callbackUrlTmp.length);
				output.write(callbackUrlTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InternalLinkTypePassportDataRequest internalLinkTypePassportDataRequest = (InternalLinkTypePassportDataRequest) o;
			if (this.botUserId != internalLinkTypePassportDataRequest.botUserId) {
				return false;
			}
			if (this.scope != internalLinkTypePassportDataRequest.scope) {
				return false;
			}
			if (this.publicKey != internalLinkTypePassportDataRequest.publicKey) {
				return false;
			}
			if (this.nonce != internalLinkTypePassportDataRequest.nonce) {
				return false;
			}
			if (this.callbackUrl != internalLinkTypePassportDataRequest.callbackUrl) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.botUserId);
			result = result * 31 + (this.scope == null ? 0 : this.scope.hashCode());
			result = result * 31 + (this.publicKey == null ? 0 : this.publicKey.hashCode());
			result = result * 31 + (this.nonce == null ? 0 : this.nonce.hashCode());
			result = result * 31 + (this.callbackUrl == null ? 0 : this.callbackUrl.hashCode());
			return result;
		}
	}

	/**
	 * The link can be used to confirm ownership of a phone number to
	 * prevent account deletion. Call sendPhoneNumberConfirmationCode with
	 * the given hash and phone number to process the link.
	**/
	public static final class InternalLinkTypePhoneNumberConfirmation extends InternalLinkType {


		/**
		 * Hash value from the link.
		**/
		public String hash;

		/**
		 * Phone number value from the link.
		**/
		public String phoneNumber;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1757375254;

		/**
		 * The link can be used to confirm ownership of a phone number to prevent account deletion. Call sendPhoneNumberConfirmationCode with the given hash and phone number to process the link.
		**/
		public InternalLinkTypePhoneNumberConfirmation() {}

		/**
		 * The link can be used to confirm ownership of a phone number to prevent account deletion. Call sendPhoneNumberConfirmationCode with the given hash and phone number to process the link.
		 *
		 * @param hash Hash value from the link.
		 * @param phoneNumber Phone number value from the link.
		**/
		public InternalLinkTypePhoneNumberConfirmation(String hash, String phoneNumber) {
			this.hash = hash;
			this.phoneNumber = phoneNumber;
		}

		/**
		 * The link can be used to confirm ownership of a phone number to prevent account deletion. Call sendPhoneNumberConfirmationCode with the given hash and phone number to process the link.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InternalLinkTypePhoneNumberConfirmation(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] hashTmp = new byte[input.readInt()];
				input.readFully(hashTmp);
				this.hash = new String(hashTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] phoneNumberTmp = new byte[input.readInt()];
				input.readFully(phoneNumberTmp);
				this.phoneNumber = new String(phoneNumberTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InternalLinkTypePhoneNumberConfirmation.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InternalLinkTypePhoneNumberConfirmation.CONSTRUCTOR);
			if (this.hash == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] hashTmp = this.hash.getBytes(StandardCharsets.UTF_8);
				output.writeInt(hashTmp.length);
				output.write(hashTmp);
			}
			if (this.phoneNumber == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] phoneNumberTmp = this.phoneNumber.getBytes(StandardCharsets.UTF_8);
				output.writeInt(phoneNumberTmp.length);
				output.write(phoneNumberTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InternalLinkTypePhoneNumberConfirmation internalLinkTypePhoneNumberConfirmation = (InternalLinkTypePhoneNumberConfirmation) o;
			if (this.hash != internalLinkTypePhoneNumberConfirmation.hash) {
				return false;
			}
			if (this.phoneNumber != internalLinkTypePhoneNumberConfirmation.phoneNumber) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.hash == null ? 0 : this.hash.hashCode();
			result = result * 31 + (this.phoneNumber == null ? 0 : this.phoneNumber.hashCode());
			return result;
		}
	}

	/**
	 * The link is a link to the Premium features screen of the application
	 * from which the user can subscribe to Telegram Premium. Call
	 * getPremiumFeatures with the given referrer to process the link.
	**/
	public static final class InternalLinkTypePremiumFeatures extends InternalLinkType {


		/**
		 * Referrer specified in the link.
		**/
		public String referrer;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1216892745;

		/**
		 * The link is a link to the Premium features screen of the application from which the user can subscribe to Telegram Premium. Call getPremiumFeatures with the given referrer to process the link.
		**/
		public InternalLinkTypePremiumFeatures() {}

		/**
		 * The link is a link to the Premium features screen of the application from which the user can subscribe to Telegram Premium. Call getPremiumFeatures with the given referrer to process the link.
		 *
		 * @param referrer Referrer specified in the link.
		**/
		public InternalLinkTypePremiumFeatures(String referrer) {
			this.referrer = referrer;
		}

		/**
		 * The link is a link to the Premium features screen of the application from which the user can subscribe to Telegram Premium. Call getPremiumFeatures with the given referrer to process the link.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InternalLinkTypePremiumFeatures(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] referrerTmp = new byte[input.readInt()];
				input.readFully(referrerTmp);
				this.referrer = new String(referrerTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InternalLinkTypePremiumFeatures.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InternalLinkTypePremiumFeatures.CONSTRUCTOR);
			if (this.referrer == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] referrerTmp = this.referrer.getBytes(StandardCharsets.UTF_8);
				output.writeInt(referrerTmp.length);
				output.write(referrerTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InternalLinkTypePremiumFeatures internalLinkTypePremiumFeatures = (InternalLinkTypePremiumFeatures) o;
			if (this.referrer != internalLinkTypePremiumFeatures.referrer) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.referrer == null ? 0 : this.referrer.hashCode();
		}
	}

	/**
	 * The link is a link to the privacy and security section of the app
	 * settings.
	**/
	public static final class InternalLinkTypePrivacyAndSecuritySettings extends InternalLinkType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1386255665;

		/**
		 * The link is a link to the privacy and security section of the app settings.
		**/
		public InternalLinkTypePrivacyAndSecuritySettings() {}

		/**
		 * The link is a link to the privacy and security section of the app settings.
		 *
		**/

		/**
		 * The link is a link to the privacy and security section of the app settings.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InternalLinkTypePrivacyAndSecuritySettings(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InternalLinkTypePrivacyAndSecuritySettings.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InternalLinkTypePrivacyAndSecuritySettings.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return InternalLinkTypePrivacyAndSecuritySettings.CONSTRUCTOR;
		}
	}

	/**
	 * The link is a link to a proxy. Call addProxy with the given
	 * parameters to process the link and add the proxy.
	**/
	public static final class InternalLinkTypeProxy extends InternalLinkType {


		/**
		 * Proxy server IP address.
		**/
		public String server;

		/**
		 * Proxy server port.
		**/
		public int port;

		/**
		 * Type of the proxy.
		**/
		public ProxyType type;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1313788694;

		/**
		 * The link is a link to a proxy. Call addProxy with the given parameters to process the link and add the proxy.
		**/
		public InternalLinkTypeProxy() {}

		/**
		 * The link is a link to a proxy. Call addProxy with the given parameters to process the link and add the proxy.
		 *
		 * @param server Proxy server IP address.
		 * @param port Proxy server port.
		 * @param type Type of the proxy.
		**/
		public InternalLinkTypeProxy(String server, int port, ProxyType type) {
			this.server = server;
			this.port = port;
			this.type = type;
		}

		/**
		 * The link is a link to a proxy. Call addProxy with the given parameters to process the link and add the proxy.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InternalLinkTypeProxy(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] serverTmp = new byte[input.readInt()];
				input.readFully(serverTmp);
				this.server = new String(serverTmp, StandardCharsets.UTF_8);
			}
			this.port = input.readInt();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ProxyTypeSocks5.CONSTRUCTOR: this.type = new ProxyTypeSocks5(input); break;
					case ProxyTypeHttp.CONSTRUCTOR: this.type = new ProxyTypeHttp(input); break;
					case ProxyTypeMtproto.CONSTRUCTOR: this.type = new ProxyTypeMtproto(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InternalLinkTypeProxy.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InternalLinkTypeProxy.CONSTRUCTOR);
			if (this.server == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] serverTmp = this.server.getBytes(StandardCharsets.UTF_8);
				output.writeInt(serverTmp.length);
				output.write(serverTmp);
			}
			output.writeInt(this.port);
			if (this.type == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.type.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InternalLinkTypeProxy internalLinkTypeProxy = (InternalLinkTypeProxy) o;
			if (this.server != internalLinkTypeProxy.server) {
				return false;
			}
			if (this.port != internalLinkTypeProxy.port) {
				return false;
			}
			if (!Objects.equals(this.type, internalLinkTypeProxy.type)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.port);
			result = result * 31 + (this.server == null ? 0 : this.server.hashCode());
			result = result * 31 + (this.type == null ? 0 : this.type.hashCode());
			return result;
		}
	}

	/**
	 * The link is a link to a chat by its username. Call searchPublicChat
	 * with the given chat username to process the link.
	**/
	public static final class InternalLinkTypePublicChat extends InternalLinkType {


		/**
		 * Username of the chat.
		**/
		public String chatUsername;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1485547717;

		/**
		 * The link is a link to a chat by its username. Call searchPublicChat with the given chat username to process the link.
		**/
		public InternalLinkTypePublicChat() {}

		/**
		 * The link is a link to a chat by its username. Call searchPublicChat with the given chat username to process the link.
		 *
		 * @param chatUsername Username of the chat.
		**/
		public InternalLinkTypePublicChat(String chatUsername) {
			this.chatUsername = chatUsername;
		}

		/**
		 * The link is a link to a chat by its username. Call searchPublicChat with the given chat username to process the link.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InternalLinkTypePublicChat(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] chatUsernameTmp = new byte[input.readInt()];
				input.readFully(chatUsernameTmp);
				this.chatUsername = new String(chatUsernameTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InternalLinkTypePublicChat.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InternalLinkTypePublicChat.CONSTRUCTOR);
			if (this.chatUsername == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] chatUsernameTmp = this.chatUsername.getBytes(StandardCharsets.UTF_8);
				output.writeInt(chatUsernameTmp.length);
				output.write(chatUsernameTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InternalLinkTypePublicChat internalLinkTypePublicChat = (InternalLinkTypePublicChat) o;
			if (this.chatUsername != internalLinkTypePublicChat.chatUsername) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.chatUsername == null ? 0 : this.chatUsername.hashCode();
		}
	}

	/**
	 * The link can be used to login the current user on another device, but
	 * it must be scanned from QR-code using in-app camera. An alert similar
	 * to &quot;This code can be used to allow someone to log in to your
	 * Telegram account. To confirm Telegram login, please go to Settings
	 * &gt; Devices &gt; Scan QR and scan the code&quot; needs to be shown.
	**/
	public static final class InternalLinkTypeQrCodeAuthentication extends InternalLinkType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1089332956;

		/**
		 * The link can be used to login the current user on another device, but it must be scanned from QR-code using in-app camera. An alert similar to &quot;This code can be used to allow someone to log in to your Telegram account. To confirm Telegram login, please go to Settings &gt; Devices &gt; Scan QR and scan the code&quot; needs to be shown.
		**/
		public InternalLinkTypeQrCodeAuthentication() {}

		/**
		 * The link can be used to login the current user on another device, but it must be scanned from QR-code using in-app camera. An alert similar to &quot;This code can be used to allow someone to log in to your Telegram account. To confirm Telegram login, please go to Settings &gt; Devices &gt; Scan QR and scan the code&quot; needs to be shown.
		 *
		**/

		/**
		 * The link can be used to login the current user on another device, but it must be scanned from QR-code using in-app camera. An alert similar to &quot;This code can be used to allow someone to log in to your Telegram account. To confirm Telegram login, please go to Settings &gt; Devices &gt; Scan QR and scan the code&quot; needs to be shown.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InternalLinkTypeQrCodeAuthentication(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InternalLinkTypeQrCodeAuthentication.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InternalLinkTypeQrCodeAuthentication.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return InternalLinkTypeQrCodeAuthentication.CONSTRUCTOR;
		}
	}

	/**
	 * The link forces restore of App Store purchases when opened. For
	 * official iOS application only.
	**/
	public static final class InternalLinkTypeRestorePurchases extends InternalLinkType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 606090371;

		/**
		 * The link forces restore of App Store purchases when opened. For official iOS application only.
		**/
		public InternalLinkTypeRestorePurchases() {}

		/**
		 * The link forces restore of App Store purchases when opened. For official iOS application only.
		 *
		**/

		/**
		 * The link forces restore of App Store purchases when opened. For official iOS application only.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InternalLinkTypeRestorePurchases(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InternalLinkTypeRestorePurchases.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InternalLinkTypeRestorePurchases.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return InternalLinkTypeRestorePurchases.CONSTRUCTOR;
		}
	}

	/**
	 * The link is a link to application settings.
	**/
	public static final class InternalLinkTypeSettings extends InternalLinkType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 393561524;

		/**
		 * The link is a link to application settings.
		**/
		public InternalLinkTypeSettings() {}

		/**
		 * The link is a link to application settings.
		 *
		**/

		/**
		 * The link is a link to application settings.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InternalLinkTypeSettings(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InternalLinkTypeSettings.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InternalLinkTypeSettings.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return InternalLinkTypeSettings.CONSTRUCTOR;
		}
	}

	/**
	 * The link is a link to a sticker set. Call searchStickerSet with the
	 * given sticker set name to process the link and show the sticker set.
	**/
	public static final class InternalLinkTypeStickerSet extends InternalLinkType {


		/**
		 * Name of the sticker set.
		**/
		public String stickerSetName;

		/**
		 * True, if the sticker set is expected to contain custom emoji.
		**/
		public boolean expectCustomEmoji;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1589227614;

		/**
		 * The link is a link to a sticker set. Call searchStickerSet with the given sticker set name to process the link and show the sticker set.
		**/
		public InternalLinkTypeStickerSet() {}

		/**
		 * The link is a link to a sticker set. Call searchStickerSet with the given sticker set name to process the link and show the sticker set.
		 *
		 * @param stickerSetName Name of the sticker set.
		 * @param expectCustomEmoji True, if the sticker set is expected to contain custom emoji.
		**/
		public InternalLinkTypeStickerSet(String stickerSetName, boolean expectCustomEmoji) {
			this.stickerSetName = stickerSetName;
			this.expectCustomEmoji = expectCustomEmoji;
		}

		/**
		 * The link is a link to a sticker set. Call searchStickerSet with the given sticker set name to process the link and show the sticker set.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InternalLinkTypeStickerSet(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] stickerSetNameTmp = new byte[input.readInt()];
				input.readFully(stickerSetNameTmp);
				this.stickerSetName = new String(stickerSetNameTmp, StandardCharsets.UTF_8);
			}
			this.expectCustomEmoji = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InternalLinkTypeStickerSet.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InternalLinkTypeStickerSet.CONSTRUCTOR);
			if (this.stickerSetName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] stickerSetNameTmp = this.stickerSetName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(stickerSetNameTmp.length);
				output.write(stickerSetNameTmp);
			}
			output.writeBoolean(this.expectCustomEmoji);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InternalLinkTypeStickerSet internalLinkTypeStickerSet = (InternalLinkTypeStickerSet) o;
			if (this.stickerSetName != internalLinkTypeStickerSet.stickerSetName) {
				return false;
			}
			if (this.expectCustomEmoji != internalLinkTypeStickerSet.expectCustomEmoji) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.expectCustomEmoji);
			result = result * 31 + (this.stickerSetName == null ? 0 : this.stickerSetName.hashCode());
			return result;
		}
	}

	/**
	 * The link is a link to a theme. TDLib has no theme support yet.
	**/
	public static final class InternalLinkTypeTheme extends InternalLinkType {


		/**
		 * Name of the theme.
		**/
		public String themeName;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -200935417;

		/**
		 * The link is a link to a theme. TDLib has no theme support yet.
		**/
		public InternalLinkTypeTheme() {}

		/**
		 * The link is a link to a theme. TDLib has no theme support yet.
		 *
		 * @param themeName Name of the theme.
		**/
		public InternalLinkTypeTheme(String themeName) {
			this.themeName = themeName;
		}

		/**
		 * The link is a link to a theme. TDLib has no theme support yet.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InternalLinkTypeTheme(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] themeNameTmp = new byte[input.readInt()];
				input.readFully(themeNameTmp);
				this.themeName = new String(themeNameTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InternalLinkTypeTheme.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InternalLinkTypeTheme.CONSTRUCTOR);
			if (this.themeName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] themeNameTmp = this.themeName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(themeNameTmp.length);
				output.write(themeNameTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InternalLinkTypeTheme internalLinkTypeTheme = (InternalLinkTypeTheme) o;
			if (this.themeName != internalLinkTypeTheme.themeName) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.themeName == null ? 0 : this.themeName.hashCode();
		}
	}

	/**
	 * The link is a link to the theme section of the app settings.
	**/
	public static final class InternalLinkTypeThemeSettings extends InternalLinkType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1051903722;

		/**
		 * The link is a link to the theme section of the app settings.
		**/
		public InternalLinkTypeThemeSettings() {}

		/**
		 * The link is a link to the theme section of the app settings.
		 *
		**/

		/**
		 * The link is a link to the theme section of the app settings.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InternalLinkTypeThemeSettings(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InternalLinkTypeThemeSettings.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InternalLinkTypeThemeSettings.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return InternalLinkTypeThemeSettings.CONSTRUCTOR;
		}
	}

	/**
	 * The link is an unknown tg: link. Call getDeepLinkInfo to process the
	 * link.
	**/
	public static final class InternalLinkTypeUnknownDeepLink extends InternalLinkType {


		/**
		 * Link to be passed to getDeepLinkInfo.
		**/
		public String link;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 625596379;

		/**
		 * The link is an unknown tg: link. Call getDeepLinkInfo to process the link.
		**/
		public InternalLinkTypeUnknownDeepLink() {}

		/**
		 * The link is an unknown tg: link. Call getDeepLinkInfo to process the link.
		 *
		 * @param link Link to be passed to getDeepLinkInfo.
		**/
		public InternalLinkTypeUnknownDeepLink(String link) {
			this.link = link;
		}

		/**
		 * The link is an unknown tg: link. Call getDeepLinkInfo to process the link.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InternalLinkTypeUnknownDeepLink(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] linkTmp = new byte[input.readInt()];
				input.readFully(linkTmp);
				this.link = new String(linkTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InternalLinkTypeUnknownDeepLink.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InternalLinkTypeUnknownDeepLink.CONSTRUCTOR);
			if (this.link == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] linkTmp = this.link.getBytes(StandardCharsets.UTF_8);
				output.writeInt(linkTmp.length);
				output.write(linkTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InternalLinkTypeUnknownDeepLink internalLinkTypeUnknownDeepLink = (InternalLinkTypeUnknownDeepLink) o;
			if (this.link != internalLinkTypeUnknownDeepLink.link) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.link == null ? 0 : this.link.hashCode();
		}
	}

	/**
	 * The link is a link to an unsupported proxy. An alert can be shown to
	 * the user.
	**/
	public static final class InternalLinkTypeUnsupportedProxy extends InternalLinkType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -566649079;

		/**
		 * The link is a link to an unsupported proxy. An alert can be shown to the user.
		**/
		public InternalLinkTypeUnsupportedProxy() {}

		/**
		 * The link is a link to an unsupported proxy. An alert can be shown to the user.
		 *
		**/

		/**
		 * The link is a link to an unsupported proxy. An alert can be shown to the user.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InternalLinkTypeUnsupportedProxy(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InternalLinkTypeUnsupportedProxy.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InternalLinkTypeUnsupportedProxy.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return InternalLinkTypeUnsupportedProxy.CONSTRUCTOR;
		}
	}

	/**
	 * The link is a link to a user by its phone number. Call
	 * searchUserByPhoneNumber with the given phone number to process the
	 * link.
	**/
	public static final class InternalLinkTypeUserPhoneNumber extends InternalLinkType {


		/**
		 * Phone number of the user.
		**/
		public String phoneNumber;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1955751319;

		/**
		 * The link is a link to a user by its phone number. Call searchUserByPhoneNumber with the given phone number to process the link.
		**/
		public InternalLinkTypeUserPhoneNumber() {}

		/**
		 * The link is a link to a user by its phone number. Call searchUserByPhoneNumber with the given phone number to process the link.
		 *
		 * @param phoneNumber Phone number of the user.
		**/
		public InternalLinkTypeUserPhoneNumber(String phoneNumber) {
			this.phoneNumber = phoneNumber;
		}

		/**
		 * The link is a link to a user by its phone number. Call searchUserByPhoneNumber with the given phone number to process the link.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InternalLinkTypeUserPhoneNumber(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] phoneNumberTmp = new byte[input.readInt()];
				input.readFully(phoneNumberTmp);
				this.phoneNumber = new String(phoneNumberTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InternalLinkTypeUserPhoneNumber.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InternalLinkTypeUserPhoneNumber.CONSTRUCTOR);
			if (this.phoneNumber == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] phoneNumberTmp = this.phoneNumber.getBytes(StandardCharsets.UTF_8);
				output.writeInt(phoneNumberTmp.length);
				output.write(phoneNumberTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InternalLinkTypeUserPhoneNumber internalLinkTypeUserPhoneNumber = (InternalLinkTypeUserPhoneNumber) o;
			if (this.phoneNumber != internalLinkTypeUserPhoneNumber.phoneNumber) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.phoneNumber == null ? 0 : this.phoneNumber.hashCode();
		}
	}

	/**
	 * The link is a link to a user by a temporary token. Call
	 * searchUserByToken with the given token to process the link.
	**/
	public static final class InternalLinkTypeUserToken extends InternalLinkType {


		/**
		 * The token.
		**/
		public String token;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1462248615;

		/**
		 * The link is a link to a user by a temporary token. Call searchUserByToken with the given token to process the link.
		**/
		public InternalLinkTypeUserToken() {}

		/**
		 * The link is a link to a user by a temporary token. Call searchUserByToken with the given token to process the link.
		 *
		 * @param token The token.
		**/
		public InternalLinkTypeUserToken(String token) {
			this.token = token;
		}

		/**
		 * The link is a link to a user by a temporary token. Call searchUserByToken with the given token to process the link.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InternalLinkTypeUserToken(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] tokenTmp = new byte[input.readInt()];
				input.readFully(tokenTmp);
				this.token = new String(tokenTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InternalLinkTypeUserToken.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InternalLinkTypeUserToken.CONSTRUCTOR);
			if (this.token == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] tokenTmp = this.token.getBytes(StandardCharsets.UTF_8);
				output.writeInt(tokenTmp.length);
				output.write(tokenTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InternalLinkTypeUserToken internalLinkTypeUserToken = (InternalLinkTypeUserToken) o;
			if (this.token != internalLinkTypeUserToken.token) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.token == null ? 0 : this.token.hashCode();
		}
	}

	/**
	 * The link is a link to a video chat. Call searchPublicChat with the
	 * given chat username, and then joinGroupCall with the given invite
	 * hash to process the link.
	**/
	public static final class InternalLinkTypeVideoChat extends InternalLinkType {


		/**
		 * Username of the chat with the video chat.
		**/
		public String chatUsername;

		/**
		 * If non-empty, invite hash to be used to join the video chat without being muted by administrators.
		**/
		public String inviteHash;

		/**
		 * True, if the video chat is expected to be a live stream in a channel or a broadcast group.
		**/
		public boolean isLiveStream;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2020149068;

		/**
		 * The link is a link to a video chat. Call searchPublicChat with the given chat username, and then joinGroupCall with the given invite hash to process the link.
		**/
		public InternalLinkTypeVideoChat() {}

		/**
		 * The link is a link to a video chat. Call searchPublicChat with the given chat username, and then joinGroupCall with the given invite hash to process the link.
		 *
		 * @param chatUsername Username of the chat with the video chat.
		 * @param inviteHash If non-empty, invite hash to be used to join the video chat without being muted by administrators.
		 * @param isLiveStream True, if the video chat is expected to be a live stream in a channel or a broadcast group.
		**/
		public InternalLinkTypeVideoChat(String chatUsername, String inviteHash, boolean isLiveStream) {
			this.chatUsername = chatUsername;
			this.inviteHash = inviteHash;
			this.isLiveStream = isLiveStream;
		}

		/**
		 * The link is a link to a video chat. Call searchPublicChat with the given chat username, and then joinGroupCall with the given invite hash to process the link.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InternalLinkTypeVideoChat(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] chatUsernameTmp = new byte[input.readInt()];
				input.readFully(chatUsernameTmp);
				this.chatUsername = new String(chatUsernameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] inviteHashTmp = new byte[input.readInt()];
				input.readFully(inviteHashTmp);
				this.inviteHash = new String(inviteHashTmp, StandardCharsets.UTF_8);
			}
			this.isLiveStream = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InternalLinkTypeVideoChat.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InternalLinkTypeVideoChat.CONSTRUCTOR);
			if (this.chatUsername == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] chatUsernameTmp = this.chatUsername.getBytes(StandardCharsets.UTF_8);
				output.writeInt(chatUsernameTmp.length);
				output.write(chatUsernameTmp);
			}
			if (this.inviteHash == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] inviteHashTmp = this.inviteHash.getBytes(StandardCharsets.UTF_8);
				output.writeInt(inviteHashTmp.length);
				output.write(inviteHashTmp);
			}
			output.writeBoolean(this.isLiveStream);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InternalLinkTypeVideoChat internalLinkTypeVideoChat = (InternalLinkTypeVideoChat) o;
			if (this.chatUsername != internalLinkTypeVideoChat.chatUsername) {
				return false;
			}
			if (this.inviteHash != internalLinkTypeVideoChat.inviteHash) {
				return false;
			}
			if (this.isLiveStream != internalLinkTypeVideoChat.isLiveStream) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isLiveStream);
			result = result * 31 + (this.chatUsername == null ? 0 : this.chatUsername.hashCode());
			result = result * 31 + (this.inviteHash == null ? 0 : this.inviteHash.hashCode());
			return result;
		}
	}

	/**
	 * The link is a link to a Web App. Call searchPublicChat with the given
	 * bot username, check that the user is a bot, then call searchWebApp
	 * with the received bot and the given webAppShortName. Process received
	 * foundWebApp by showing a confirmation dialog if needed, then calling
	 * getWebAppLinkUrl and opening the returned URL.
	**/
	public static final class InternalLinkTypeWebApp extends InternalLinkType {


		/**
		 * Username of the bot that owns the Web App.
		**/
		public String botUsername;

		/**
		 * Short name of the Web App.
		**/
		public String webAppShortName;

		/**
		 * Start parameter to be passed to getWebAppLinkUrl.
		**/
		public String startParameter;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -57094065;

		/**
		 * The link is a link to a Web App. Call searchPublicChat with the given bot username, check that the user is a bot, then call searchWebApp with the received bot and the given webAppShortName. Process received foundWebApp by showing a confirmation dialog if needed, then calling getWebAppLinkUrl and opening the returned URL.
		**/
		public InternalLinkTypeWebApp() {}

		/**
		 * The link is a link to a Web App. Call searchPublicChat with the given bot username, check that the user is a bot, then call searchWebApp with the received bot and the given webAppShortName. Process received foundWebApp by showing a confirmation dialog if needed, then calling getWebAppLinkUrl and opening the returned URL.
		 *
		 * @param botUsername Username of the bot that owns the Web App.
		 * @param webAppShortName Short name of the Web App.
		 * @param startParameter Start parameter to be passed to getWebAppLinkUrl.
		**/
		public InternalLinkTypeWebApp(String botUsername,
				String webAppShortName,
				String startParameter) {
			this.botUsername = botUsername;
			this.webAppShortName = webAppShortName;
			this.startParameter = startParameter;
		}

		/**
		 * The link is a link to a Web App. Call searchPublicChat with the given bot username, check that the user is a bot, then call searchWebApp with the received bot and the given webAppShortName. Process received foundWebApp by showing a confirmation dialog if needed, then calling getWebAppLinkUrl and opening the returned URL.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InternalLinkTypeWebApp(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] botUsernameTmp = new byte[input.readInt()];
				input.readFully(botUsernameTmp);
				this.botUsername = new String(botUsernameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] webAppShortNameTmp = new byte[input.readInt()];
				input.readFully(webAppShortNameTmp);
				this.webAppShortName = new String(webAppShortNameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] startParameterTmp = new byte[input.readInt()];
				input.readFully(startParameterTmp);
				this.startParameter = new String(startParameterTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InternalLinkTypeWebApp.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InternalLinkTypeWebApp.CONSTRUCTOR);
			if (this.botUsername == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] botUsernameTmp = this.botUsername.getBytes(StandardCharsets.UTF_8);
				output.writeInt(botUsernameTmp.length);
				output.write(botUsernameTmp);
			}
			if (this.webAppShortName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] webAppShortNameTmp = this.webAppShortName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(webAppShortNameTmp.length);
				output.write(webAppShortNameTmp);
			}
			if (this.startParameter == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] startParameterTmp = this.startParameter.getBytes(StandardCharsets.UTF_8);
				output.writeInt(startParameterTmp.length);
				output.write(startParameterTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InternalLinkTypeWebApp internalLinkTypeWebApp = (InternalLinkTypeWebApp) o;
			if (this.botUsername != internalLinkTypeWebApp.botUsername) {
				return false;
			}
			if (this.webAppShortName != internalLinkTypeWebApp.webAppShortName) {
				return false;
			}
			if (this.startParameter != internalLinkTypeWebApp.startParameter) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.botUsername == null ? 0 : this.botUsername.hashCode();
			result = result * 31 + (this.webAppShortName == null ? 0 : this.webAppShortName.hashCode());
			result = result * 31 + (this.startParameter == null ? 0 : this.startParameter.hashCode());
			return result;
		}
	}

	/**
	 * Product invoice.
	**/
	public static final class Invoice extends Object {


		/**
		 * ISO 4217 currency code.
		**/
		public String currency;

		/**
		 * A list of objects used to calculate the total price of the product.
		**/
		public LabeledPricePart[] priceParts;

		/**
		 * The maximum allowed amount of tip in the smallest units of the currency.
		**/
		public long maxTipAmount;

		/**
		 * Suggested amounts of tip in the smallest units of the currency.
		**/
		public long[] suggestedTipAmounts;

		/**
		 * An HTTP URL with terms of service for recurring payments. If non-empty, the invoice payment will result in recurring payments and the user must accept the terms of service before allowed to pay.
		**/
		public String recurringPaymentTermsOfServiceUrl;

		/**
		 * True, if the payment is a test payment.
		**/
		public boolean isTest;

		/**
		 * True, if the user&#039;s name is needed for payment.
		**/
		public boolean needName;

		/**
		 * True, if the user&#039;s phone number is needed for payment.
		**/
		public boolean needPhoneNumber;

		/**
		 * True, if the user&#039;s email address is needed for payment.
		**/
		public boolean needEmailAddress;

		/**
		 * True, if the user&#039;s shipping address is needed for payment.
		**/
		public boolean needShippingAddress;

		/**
		 * True, if the user&#039;s phone number will be sent to the provider.
		**/
		public boolean sendPhoneNumberToProvider;

		/**
		 * True, if the user&#039;s email address will be sent to the provider.
		**/
		public boolean sendEmailAddressToProvider;

		/**
		 * True, if the total price depends on the shipping method.
		**/
		public boolean isFlexible;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1977205639;

		/**
		 * Product invoice.
		**/
		public Invoice() {}

		/**
		 * Product invoice.
		 *
		 * @param currency ISO 4217 currency code.
		 * @param priceParts A list of objects used to calculate the total price of the product.
		 * @param maxTipAmount The maximum allowed amount of tip in the smallest units of the currency.
		 * @param suggestedTipAmounts Suggested amounts of tip in the smallest units of the currency.
		 * @param recurringPaymentTermsOfServiceUrl An HTTP URL with terms of service for recurring payments. If non-empty, the invoice payment will result in recurring payments and the user must accept the terms of service before allowed to pay.
		 * @param isTest True, if the payment is a test payment.
		 * @param needName True, if the user&#039;s name is needed for payment.
		 * @param needPhoneNumber True, if the user&#039;s phone number is needed for payment.
		 * @param needEmailAddress True, if the user&#039;s email address is needed for payment.
		 * @param needShippingAddress True, if the user&#039;s shipping address is needed for payment.
		 * @param sendPhoneNumberToProvider True, if the user&#039;s phone number will be sent to the provider.
		 * @param sendEmailAddressToProvider True, if the user&#039;s email address will be sent to the provider.
		 * @param isFlexible True, if the total price depends on the shipping method.
		**/
		public Invoice(String currency,
				LabeledPricePart[] priceParts,
				long maxTipAmount,
				long[] suggestedTipAmounts,
				String recurringPaymentTermsOfServiceUrl,
				boolean isTest,
				boolean needName,
				boolean needPhoneNumber,
				boolean needEmailAddress,
				boolean needShippingAddress,
				boolean sendPhoneNumberToProvider,
				boolean sendEmailAddressToProvider,
				boolean isFlexible) {
			this.currency = currency;
			this.priceParts = priceParts;
			this.maxTipAmount = maxTipAmount;
			this.suggestedTipAmounts = suggestedTipAmounts;
			this.recurringPaymentTermsOfServiceUrl = recurringPaymentTermsOfServiceUrl;
			this.isTest = isTest;
			this.needName = needName;
			this.needPhoneNumber = needPhoneNumber;
			this.needEmailAddress = needEmailAddress;
			this.needShippingAddress = needShippingAddress;
			this.sendPhoneNumberToProvider = sendPhoneNumberToProvider;
			this.sendEmailAddressToProvider = sendEmailAddressToProvider;
			this.isFlexible = isFlexible;
		}

		/**
		 * Product invoice.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public Invoice(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] currencyTmp = new byte[input.readInt()];
				input.readFully(currencyTmp);
				this.currency = new String(currencyTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				this.priceParts = new LabeledPricePart[input.readInt()];
				for (int i = 0; i < this.priceParts.length; i++) {
					if (LabeledPricePart.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.priceParts[i] = new LabeledPricePart(input);
				}
			}
			this.maxTipAmount = input.readLong();
			if (input.readBoolean()) {
				this.suggestedTipAmounts = new long[input.readInt()];
				for (int i = 0; i < this.suggestedTipAmounts.length; i++) {
					this.suggestedTipAmounts[i] = input.readLong();
				}
			}
			if (input.readBoolean()) {
				byte[] recurringPaymentTermsOfServiceUrlTmp = new byte[input.readInt()];
				input.readFully(recurringPaymentTermsOfServiceUrlTmp);
				this.recurringPaymentTermsOfServiceUrl = new String(recurringPaymentTermsOfServiceUrlTmp, StandardCharsets.UTF_8);
			}
			this.isTest = input.readBoolean();
			this.needName = input.readBoolean();
			this.needPhoneNumber = input.readBoolean();
			this.needEmailAddress = input.readBoolean();
			this.needShippingAddress = input.readBoolean();
			this.sendPhoneNumberToProvider = input.readBoolean();
			this.sendEmailAddressToProvider = input.readBoolean();
			this.isFlexible = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return Invoice.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(Invoice.CONSTRUCTOR);
			if (this.currency == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] currencyTmp = this.currency.getBytes(StandardCharsets.UTF_8);
				output.writeInt(currencyTmp.length);
				output.write(currencyTmp);
			}
			if (this.priceParts == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.priceParts.length);
				for (int i = 0; i < this.priceParts.length; i++) {
					this.priceParts[i].serialize(output);
				}
			}
			output.writeLong(this.maxTipAmount);
			if (this.suggestedTipAmounts == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.suggestedTipAmounts.length);
				for (int i = 0; i < this.suggestedTipAmounts.length; i++) {
					output.writeLong(this.suggestedTipAmounts[i]);
				}
			}
			if (this.recurringPaymentTermsOfServiceUrl == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] recurringPaymentTermsOfServiceUrlTmp = this.recurringPaymentTermsOfServiceUrl.getBytes(StandardCharsets.UTF_8);
				output.writeInt(recurringPaymentTermsOfServiceUrlTmp.length);
				output.write(recurringPaymentTermsOfServiceUrlTmp);
			}
			output.writeBoolean(this.isTest);
			output.writeBoolean(this.needName);
			output.writeBoolean(this.needPhoneNumber);
			output.writeBoolean(this.needEmailAddress);
			output.writeBoolean(this.needShippingAddress);
			output.writeBoolean(this.sendPhoneNumberToProvider);
			output.writeBoolean(this.sendEmailAddressToProvider);
			output.writeBoolean(this.isFlexible);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			Invoice invoice = (Invoice) o;
			if (this.currency != invoice.currency) {
				return false;
			}
			if (!Arrays.equals(this.priceParts, invoice.priceParts)) {
				return false;
			}
			if (this.maxTipAmount != invoice.maxTipAmount) {
				return false;
			}
			if (!Arrays.equals(this.suggestedTipAmounts, invoice.suggestedTipAmounts)) {
				return false;
			}
			if (this.recurringPaymentTermsOfServiceUrl != invoice.recurringPaymentTermsOfServiceUrl) {
				return false;
			}
			if (this.isTest != invoice.isTest) {
				return false;
			}
			if (this.needName != invoice.needName) {
				return false;
			}
			if (this.needPhoneNumber != invoice.needPhoneNumber) {
				return false;
			}
			if (this.needEmailAddress != invoice.needEmailAddress) {
				return false;
			}
			if (this.needShippingAddress != invoice.needShippingAddress) {
				return false;
			}
			if (this.sendPhoneNumberToProvider != invoice.sendPhoneNumberToProvider) {
				return false;
			}
			if (this.sendEmailAddressToProvider != invoice.sendEmailAddressToProvider) {
				return false;
			}
			if (this.isFlexible != invoice.isFlexible) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.maxTipAmount);
			result = result * 31 + (this.currency == null ? 0 : this.currency.hashCode());
			result = result * 31 + (Arrays.hashCode(this.priceParts));
			result = result * 31 + (Arrays.hashCode(this.suggestedTipAmounts));
			result = result * 31 + (this.recurringPaymentTermsOfServiceUrl == null ? 0 : this.recurringPaymentTermsOfServiceUrl.hashCode());
			return result;
		}
	}

	/**
	 * Represents one member of a JSON object.
	**/
	public static final class JsonObjectMember extends Object {


		/**
		 * Member&#039;s key.
		**/
		public String key;

		/**
		 * Member&#039;s value.
		**/
		public JsonValue value;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1803309418;

		/**
		 * Represents one member of a JSON object.
		**/
		public JsonObjectMember() {}

		/**
		 * Represents one member of a JSON object.
		 *
		 * @param key Member&#039;s key.
		 * @param value Member&#039;s value.
		**/
		public JsonObjectMember(String key, JsonValue value) {
			this.key = key;
			this.value = value;
		}

		/**
		 * Represents one member of a JSON object.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public JsonObjectMember(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] keyTmp = new byte[input.readInt()];
				input.readFully(keyTmp);
				this.key = new String(keyTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case JsonValueNull.CONSTRUCTOR: this.value = new JsonValueNull(input); break;
					case JsonValueBoolean.CONSTRUCTOR: this.value = new JsonValueBoolean(input); break;
					case JsonValueNumber.CONSTRUCTOR: this.value = new JsonValueNumber(input); break;
					case JsonValueString.CONSTRUCTOR: this.value = new JsonValueString(input); break;
					case JsonValueArray.CONSTRUCTOR: this.value = new JsonValueArray(input); break;
					case JsonValueObject.CONSTRUCTOR: this.value = new JsonValueObject(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return JsonObjectMember.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(JsonObjectMember.CONSTRUCTOR);
			if (this.key == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] keyTmp = this.key.getBytes(StandardCharsets.UTF_8);
				output.writeInt(keyTmp.length);
				output.write(keyTmp);
			}
			if (this.value == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.value.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			JsonObjectMember jsonObjectMember = (JsonObjectMember) o;
			if (this.key != jsonObjectMember.key) {
				return false;
			}
			if (!Objects.equals(this.value, jsonObjectMember.value)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.key == null ? 0 : this.key.hashCode();
			result = result * 31 + (this.value == null ? 0 : this.value.hashCode());
			return result;
		}
	}

	/**
	 * Represents a null JSON value.
	**/
	public static final class JsonValueNull extends JsonValue {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -92872499;

		/**
		 * Represents a null JSON value.
		**/
		public JsonValueNull() {}

		/**
		 * Represents a null JSON value.
		 *
		**/

		/**
		 * Represents a null JSON value.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public JsonValueNull(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return JsonValueNull.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(JsonValueNull.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return JsonValueNull.CONSTRUCTOR;
		}
	}

	/**
	 * Represents a boolean JSON value.
	**/
	public static final class JsonValueBoolean extends JsonValue {


		/**
		 * The value.
		**/
		public boolean value;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2142186576;

		/**
		 * Represents a boolean JSON value.
		**/
		public JsonValueBoolean() {}

		/**
		 * Represents a boolean JSON value.
		 *
		 * @param value The value.
		**/
		public JsonValueBoolean(boolean value) {
			this.value = value;
		}

		/**
		 * Represents a boolean JSON value.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public JsonValueBoolean(DataInput input) throws IOException {
			this.value = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return JsonValueBoolean.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(JsonValueBoolean.CONSTRUCTOR);
			output.writeBoolean(this.value);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			JsonValueBoolean jsonValueBoolean = (JsonValueBoolean) o;
			if (this.value != jsonValueBoolean.value) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Boolean.hashCode(this.value);
		}
	}

	/**
	 * Represents a numeric JSON value.
	**/
	public static final class JsonValueNumber extends JsonValue {


		/**
		 * The value.
		**/
		public double value;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1010822033;

		/**
		 * Represents a numeric JSON value.
		**/
		public JsonValueNumber() {}

		/**
		 * Represents a numeric JSON value.
		 *
		 * @param value The value.
		**/
		public JsonValueNumber(double value) {
			this.value = value;
		}

		/**
		 * Represents a numeric JSON value.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public JsonValueNumber(DataInput input) throws IOException {
			this.value = input.readDouble();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return JsonValueNumber.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(JsonValueNumber.CONSTRUCTOR);
			output.writeDouble(this.value);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			JsonValueNumber jsonValueNumber = (JsonValueNumber) o;
			if (this.value != jsonValueNumber.value) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Double.hashCode(this.value);
		}
	}

	/**
	 * Represents a string JSON value.
	**/
	public static final class JsonValueString extends JsonValue {


		/**
		 * The value.
		**/
		public String value;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1597947313;

		/**
		 * Represents a string JSON value.
		**/
		public JsonValueString() {}

		/**
		 * Represents a string JSON value.
		 *
		 * @param value The value.
		**/
		public JsonValueString(String value) {
			this.value = value;
		}

		/**
		 * Represents a string JSON value.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public JsonValueString(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] valueTmp = new byte[input.readInt()];
				input.readFully(valueTmp);
				this.value = new String(valueTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return JsonValueString.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(JsonValueString.CONSTRUCTOR);
			if (this.value == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] valueTmp = this.value.getBytes(StandardCharsets.UTF_8);
				output.writeInt(valueTmp.length);
				output.write(valueTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			JsonValueString jsonValueString = (JsonValueString) o;
			if (this.value != jsonValueString.value) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.value == null ? 0 : this.value.hashCode();
		}
	}

	/**
	 * Represents a JSON array.
	**/
	public static final class JsonValueArray extends JsonValue {


		/**
		 * The list of array elements.
		**/
		public JsonValue[] values;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -183913546;

		/**
		 * Represents a JSON array.
		**/
		public JsonValueArray() {}

		/**
		 * Represents a JSON array.
		 *
		 * @param values The list of array elements.
		**/
		public JsonValueArray(JsonValue[] values) {
			this.values = values;
		}

		/**
		 * Represents a JSON array.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public JsonValueArray(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.values = new JsonValue[input.readInt()];
				for (int i = 0; i < this.values.length; i++) {
					switch(input.readInt()) {
						case JsonValueNull.CONSTRUCTOR: this.values[i] = new JsonValueNull(input); break;
						case JsonValueBoolean.CONSTRUCTOR: this.values[i] = new JsonValueBoolean(input); break;
						case JsonValueNumber.CONSTRUCTOR: this.values[i] = new JsonValueNumber(input); break;
						case JsonValueString.CONSTRUCTOR: this.values[i] = new JsonValueString(input); break;
						case JsonValueArray.CONSTRUCTOR: this.values[i] = new JsonValueArray(input); break;
						case JsonValueObject.CONSTRUCTOR: this.values[i] = new JsonValueObject(input); break;
						default: {
							throw new UnsupportedOperationException();
						}
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return JsonValueArray.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(JsonValueArray.CONSTRUCTOR);
			if (this.values == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.values.length);
				for (int i = 0; i < this.values.length; i++) {
					this.values[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			JsonValueArray jsonValueArray = (JsonValueArray) o;
			if (!Arrays.equals(this.values, jsonValueArray.values)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.values);
		}
	}

	/**
	 * Represents a JSON object.
	**/
	public static final class JsonValueObject extends JsonValue {


		/**
		 * The list of object members.
		**/
		public JsonObjectMember[] members;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 520252026;

		/**
		 * Represents a JSON object.
		**/
		public JsonValueObject() {}

		/**
		 * Represents a JSON object.
		 *
		 * @param members The list of object members.
		**/
		public JsonValueObject(JsonObjectMember[] members) {
			this.members = members;
		}

		/**
		 * Represents a JSON object.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public JsonValueObject(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.members = new JsonObjectMember[input.readInt()];
				for (int i = 0; i < this.members.length; i++) {
					if (JsonObjectMember.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.members[i] = new JsonObjectMember(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return JsonValueObject.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(JsonValueObject.CONSTRUCTOR);
			if (this.members == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.members.length);
				for (int i = 0; i < this.members.length; i++) {
					this.members[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			JsonValueObject jsonValueObject = (JsonValueObject) o;
			if (!Arrays.equals(this.members, jsonValueObject.members)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.members);
		}
	}

	/**
	 * Represents a single button in a bot keyboard.
	**/
	public static final class KeyboardButton extends Object {


		/**
		 * Text of the button.
		**/
		public String text;

		/**
		 * Type of the button.
		**/
		public KeyboardButtonType type;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2069836172;

		/**
		 * Represents a single button in a bot keyboard.
		**/
		public KeyboardButton() {}

		/**
		 * Represents a single button in a bot keyboard.
		 *
		 * @param text Text of the button.
		 * @param type Type of the button.
		**/
		public KeyboardButton(String text, KeyboardButtonType type) {
			this.text = text;
			this.type = type;
		}

		/**
		 * Represents a single button in a bot keyboard.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public KeyboardButton(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] textTmp = new byte[input.readInt()];
				input.readFully(textTmp);
				this.text = new String(textTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case KeyboardButtonTypeText.CONSTRUCTOR: this.type = new KeyboardButtonTypeText(input); break;
					case KeyboardButtonTypeRequestPhoneNumber.CONSTRUCTOR: this.type = new KeyboardButtonTypeRequestPhoneNumber(input); break;
					case KeyboardButtonTypeRequestLocation.CONSTRUCTOR: this.type = new KeyboardButtonTypeRequestLocation(input); break;
					case KeyboardButtonTypeRequestPoll.CONSTRUCTOR: this.type = new KeyboardButtonTypeRequestPoll(input); break;
					case KeyboardButtonTypeRequestUser.CONSTRUCTOR: this.type = new KeyboardButtonTypeRequestUser(input); break;
					case KeyboardButtonTypeRequestChat.CONSTRUCTOR: this.type = new KeyboardButtonTypeRequestChat(input); break;
					case KeyboardButtonTypeWebApp.CONSTRUCTOR: this.type = new KeyboardButtonTypeWebApp(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return KeyboardButton.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(KeyboardButton.CONSTRUCTOR);
			if (this.text == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] textTmp = this.text.getBytes(StandardCharsets.UTF_8);
				output.writeInt(textTmp.length);
				output.write(textTmp);
			}
			if (this.type == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.type.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			KeyboardButton keyboardButton = (KeyboardButton) o;
			if (this.text != keyboardButton.text) {
				return false;
			}
			if (!Objects.equals(this.type, keyboardButton.type)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.text == null ? 0 : this.text.hashCode();
			result = result * 31 + (this.type == null ? 0 : this.type.hashCode());
			return result;
		}
	}

	/**
	 * A simple button, with text that must be sent when the button is
	 * pressed.
	**/
	public static final class KeyboardButtonTypeText extends KeyboardButtonType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1773037256;

		/**
		 * A simple button, with text that must be sent when the button is pressed.
		**/
		public KeyboardButtonTypeText() {}

		/**
		 * A simple button, with text that must be sent when the button is pressed.
		 *
		**/

		/**
		 * A simple button, with text that must be sent when the button is pressed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public KeyboardButtonTypeText(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return KeyboardButtonTypeText.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(KeyboardButtonTypeText.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return KeyboardButtonTypeText.CONSTRUCTOR;
		}
	}

	/**
	 * A button that sends the user&#039;s phone number when pressed;
	 * available only in private chats.
	**/
	public static final class KeyboardButtonTypeRequestPhoneNumber extends KeyboardButtonType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1529235527;

		/**
		 * A button that sends the user&#039;s phone number when pressed; available only in private chats.
		**/
		public KeyboardButtonTypeRequestPhoneNumber() {}

		/**
		 * A button that sends the user&#039;s phone number when pressed; available only in private chats.
		 *
		**/

		/**
		 * A button that sends the user&#039;s phone number when pressed; available only in private chats.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public KeyboardButtonTypeRequestPhoneNumber(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return KeyboardButtonTypeRequestPhoneNumber.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(KeyboardButtonTypeRequestPhoneNumber.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return KeyboardButtonTypeRequestPhoneNumber.CONSTRUCTOR;
		}
	}

	/**
	 * A button that sends the user&#039;s location when pressed; available
	 * only in private chats.
	**/
	public static final class KeyboardButtonTypeRequestLocation extends KeyboardButtonType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -125661955;

		/**
		 * A button that sends the user&#039;s location when pressed; available only in private chats.
		**/
		public KeyboardButtonTypeRequestLocation() {}

		/**
		 * A button that sends the user&#039;s location when pressed; available only in private chats.
		 *
		**/

		/**
		 * A button that sends the user&#039;s location when pressed; available only in private chats.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public KeyboardButtonTypeRequestLocation(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return KeyboardButtonTypeRequestLocation.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(KeyboardButtonTypeRequestLocation.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return KeyboardButtonTypeRequestLocation.CONSTRUCTOR;
		}
	}

	/**
	 * A button that allows the user to create and send a poll when pressed;
	 * available only in private chats.
	**/
	public static final class KeyboardButtonTypeRequestPoll extends KeyboardButtonType {


		/**
		 * If true, only regular polls must be allowed to create.
		**/
		public boolean forceRegular;

		/**
		 * If true, only polls in quiz mode must be allowed to create.
		**/
		public boolean forceQuiz;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1902435512;

		/**
		 * A button that allows the user to create and send a poll when pressed; available only in private chats.
		**/
		public KeyboardButtonTypeRequestPoll() {}

		/**
		 * A button that allows the user to create and send a poll when pressed; available only in private chats.
		 *
		 * @param forceRegular If true, only regular polls must be allowed to create.
		 * @param forceQuiz If true, only polls in quiz mode must be allowed to create.
		**/
		public KeyboardButtonTypeRequestPoll(boolean forceRegular, boolean forceQuiz) {
			this.forceRegular = forceRegular;
			this.forceQuiz = forceQuiz;
		}

		/**
		 * A button that allows the user to create and send a poll when pressed; available only in private chats.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public KeyboardButtonTypeRequestPoll(DataInput input) throws IOException {
			this.forceRegular = input.readBoolean();
			this.forceQuiz = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return KeyboardButtonTypeRequestPoll.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(KeyboardButtonTypeRequestPoll.CONSTRUCTOR);
			output.writeBoolean(this.forceRegular);
			output.writeBoolean(this.forceQuiz);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			KeyboardButtonTypeRequestPoll keyboardButtonTypeRequestPoll = (KeyboardButtonTypeRequestPoll) o;
			if (this.forceRegular != keyboardButtonTypeRequestPoll.forceRegular) {
				return false;
			}
			if (this.forceQuiz != keyboardButtonTypeRequestPoll.forceQuiz) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.forceRegular);
			return result;
		}
	}

	/**
	 * A button that requests a user to be shared by the current user;
	 * available only in private chats. Use the method shareUserWithBot to
	 * complete the request.
	**/
	public static final class KeyboardButtonTypeRequestUser extends KeyboardButtonType {


		/**
		 * Unique button identifier.
		**/
		public int id;

		/**
		 * True, if the shared user must or must not be a bot.
		**/
		public boolean restrictUserIsBot;

		/**
		 * True, if the shared user must be a bot; otherwise, the shared user must no be a bot. Ignored if restrictUserIsBot is false.
		**/
		public boolean userIsBot;

		/**
		 * True, if the shared user must or must not be a Telegram Premium user.
		**/
		public boolean restrictUserIsPremium;

		/**
		 * True, if the shared user must be a Telegram Premium user; otherwise, the shared user must no be a Telegram Premium user. Ignored if restrictUserIsPremium is false.
		**/
		public boolean userIsPremium;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1996508112;

		/**
		 * A button that requests a user to be shared by the current user; available only in private chats. Use the method shareUserWithBot to complete the request.
		**/
		public KeyboardButtonTypeRequestUser() {}

		/**
		 * A button that requests a user to be shared by the current user; available only in private chats. Use the method shareUserWithBot to complete the request.
		 *
		 * @param id Unique button identifier.
		 * @param restrictUserIsBot True, if the shared user must or must not be a bot.
		 * @param userIsBot True, if the shared user must be a bot; otherwise, the shared user must no be a bot. Ignored if restrictUserIsBot is false.
		 * @param restrictUserIsPremium True, if the shared user must or must not be a Telegram Premium user.
		 * @param userIsPremium True, if the shared user must be a Telegram Premium user; otherwise, the shared user must no be a Telegram Premium user. Ignored if restrictUserIsPremium is false.
		**/
		public KeyboardButtonTypeRequestUser(int id,
				boolean restrictUserIsBot,
				boolean userIsBot,
				boolean restrictUserIsPremium,
				boolean userIsPremium) {
			this.id = id;
			this.restrictUserIsBot = restrictUserIsBot;
			this.userIsBot = userIsBot;
			this.restrictUserIsPremium = restrictUserIsPremium;
			this.userIsPremium = userIsPremium;
		}

		/**
		 * A button that requests a user to be shared by the current user; available only in private chats. Use the method shareUserWithBot to complete the request.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public KeyboardButtonTypeRequestUser(DataInput input) throws IOException {
			this.id = input.readInt();
			this.restrictUserIsBot = input.readBoolean();
			this.userIsBot = input.readBoolean();
			this.restrictUserIsPremium = input.readBoolean();
			this.userIsPremium = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return KeyboardButtonTypeRequestUser.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(KeyboardButtonTypeRequestUser.CONSTRUCTOR);
			output.writeInt(this.id);
			output.writeBoolean(this.restrictUserIsBot);
			output.writeBoolean(this.userIsBot);
			output.writeBoolean(this.restrictUserIsPremium);
			output.writeBoolean(this.userIsPremium);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			KeyboardButtonTypeRequestUser keyboardButtonTypeRequestUser = (KeyboardButtonTypeRequestUser) o;
			if (this.id != keyboardButtonTypeRequestUser.id) {
				return false;
			}
			if (this.restrictUserIsBot != keyboardButtonTypeRequestUser.restrictUserIsBot) {
				return false;
			}
			if (this.userIsBot != keyboardButtonTypeRequestUser.userIsBot) {
				return false;
			}
			if (this.restrictUserIsPremium != keyboardButtonTypeRequestUser.restrictUserIsPremium) {
				return false;
			}
			if (this.userIsPremium != keyboardButtonTypeRequestUser.userIsPremium) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.id);
			return result;
		}
	}

	/**
	 * A button that requests a chat to be shared by the current user;
	 * available only in private chats. Use the method shareChatWithBot to
	 * complete the request.
	**/
	public static final class KeyboardButtonTypeRequestChat extends KeyboardButtonType {


		/**
		 * Unique button identifier.
		**/
		public int id;

		/**
		 * True, if the chat must be a channel; otherwise, a basic group or a supergroup chat is shared.
		**/
		public boolean chatIsChannel;

		/**
		 * True, if the chat must or must not be a forum supergroup.
		**/
		public boolean restrictChatIsForum;

		/**
		 * True, if the chat must be a forum supergroup; otherwise, the chat must not be a forum supergroup. Ignored if restrictChatIsForum is false.
		**/
		public boolean chatIsForum;

		/**
		 * True, if the chat must or must not have a username.
		**/
		public boolean restrictChatHasUsername;

		/**
		 * True, if the chat must have a username; otherwise, the chat must not have a username. Ignored if restrictChatHasUsername is false.
		**/
		public boolean chatHasUsername;

		/**
		 * True, if the chat must be created by the current user.
		**/
		public boolean chatIsCreated;

		/**
		 * Expected user administrator rights in the chat; may be null if they aren&#039;t restricted.
		**/
		public ChatAdministratorRights userAdministratorRights;

		/**
		 * Expected bot administrator rights in the chat; may be null if they aren&#039;t restricted.
		**/
		public ChatAdministratorRights botAdministratorRights;

		/**
		 * True, if the bot must be a member of the chat; for basic group and supergroup chats only.
		**/
		public boolean botIsMember;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 272541602;

		/**
		 * A button that requests a chat to be shared by the current user; available only in private chats. Use the method shareChatWithBot to complete the request.
		**/
		public KeyboardButtonTypeRequestChat() {}

		/**
		 * A button that requests a chat to be shared by the current user; available only in private chats. Use the method shareChatWithBot to complete the request.
		 *
		 * @param id Unique button identifier.
		 * @param chatIsChannel True, if the chat must be a channel; otherwise, a basic group or a supergroup chat is shared.
		 * @param restrictChatIsForum True, if the chat must or must not be a forum supergroup.
		 * @param chatIsForum True, if the chat must be a forum supergroup; otherwise, the chat must not be a forum supergroup. Ignored if restrictChatIsForum is false.
		 * @param restrictChatHasUsername True, if the chat must or must not have a username.
		 * @param chatHasUsername True, if the chat must have a username; otherwise, the chat must not have a username. Ignored if restrictChatHasUsername is false.
		 * @param chatIsCreated True, if the chat must be created by the current user.
		 * @param userAdministratorRights Expected user administrator rights in the chat; may be null if they aren&#039;t restricted.
		 * @param botAdministratorRights Expected bot administrator rights in the chat; may be null if they aren&#039;t restricted.
		 * @param botIsMember True, if the bot must be a member of the chat; for basic group and supergroup chats only.
		**/
		public KeyboardButtonTypeRequestChat(int id,
				boolean chatIsChannel,
				boolean restrictChatIsForum,
				boolean chatIsForum,
				boolean restrictChatHasUsername,
				boolean chatHasUsername,
				boolean chatIsCreated,
				ChatAdministratorRights userAdministratorRights,
				ChatAdministratorRights botAdministratorRights,
				boolean botIsMember) {
			this.id = id;
			this.chatIsChannel = chatIsChannel;
			this.restrictChatIsForum = restrictChatIsForum;
			this.chatIsForum = chatIsForum;
			this.restrictChatHasUsername = restrictChatHasUsername;
			this.chatHasUsername = chatHasUsername;
			this.chatIsCreated = chatIsCreated;
			this.userAdministratorRights = userAdministratorRights;
			this.botAdministratorRights = botAdministratorRights;
			this.botIsMember = botIsMember;
		}

		/**
		 * A button that requests a chat to be shared by the current user; available only in private chats. Use the method shareChatWithBot to complete the request.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public KeyboardButtonTypeRequestChat(DataInput input) throws IOException {
			this.id = input.readInt();
			this.chatIsChannel = input.readBoolean();
			this.restrictChatIsForum = input.readBoolean();
			this.chatIsForum = input.readBoolean();
			this.restrictChatHasUsername = input.readBoolean();
			this.chatHasUsername = input.readBoolean();
			this.chatIsCreated = input.readBoolean();
			if (input.readBoolean()) {
				if (ChatAdministratorRights.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.userAdministratorRights = new ChatAdministratorRights(input);
			}
			if (input.readBoolean()) {
				if (ChatAdministratorRights.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.botAdministratorRights = new ChatAdministratorRights(input);
			}
			this.botIsMember = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return KeyboardButtonTypeRequestChat.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(KeyboardButtonTypeRequestChat.CONSTRUCTOR);
			output.writeInt(this.id);
			output.writeBoolean(this.chatIsChannel);
			output.writeBoolean(this.restrictChatIsForum);
			output.writeBoolean(this.chatIsForum);
			output.writeBoolean(this.restrictChatHasUsername);
			output.writeBoolean(this.chatHasUsername);
			output.writeBoolean(this.chatIsCreated);
			if (this.userAdministratorRights == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.userAdministratorRights.serialize(output);
			}
			if (this.botAdministratorRights == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.botAdministratorRights.serialize(output);
			}
			output.writeBoolean(this.botIsMember);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			KeyboardButtonTypeRequestChat keyboardButtonTypeRequestChat = (KeyboardButtonTypeRequestChat) o;
			if (this.id != keyboardButtonTypeRequestChat.id) {
				return false;
			}
			if (this.chatIsChannel != keyboardButtonTypeRequestChat.chatIsChannel) {
				return false;
			}
			if (this.restrictChatIsForum != keyboardButtonTypeRequestChat.restrictChatIsForum) {
				return false;
			}
			if (this.chatIsForum != keyboardButtonTypeRequestChat.chatIsForum) {
				return false;
			}
			if (this.restrictChatHasUsername != keyboardButtonTypeRequestChat.restrictChatHasUsername) {
				return false;
			}
			if (this.chatHasUsername != keyboardButtonTypeRequestChat.chatHasUsername) {
				return false;
			}
			if (this.chatIsCreated != keyboardButtonTypeRequestChat.chatIsCreated) {
				return false;
			}
			if (!Objects.equals(this.userAdministratorRights, keyboardButtonTypeRequestChat.userAdministratorRights)) {
				return false;
			}
			if (!Objects.equals(this.botAdministratorRights, keyboardButtonTypeRequestChat.botAdministratorRights)) {
				return false;
			}
			if (this.botIsMember != keyboardButtonTypeRequestChat.botIsMember) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.id);
			result = result * 31 + (this.userAdministratorRights == null ? 0 : this.userAdministratorRights.hashCode());
			result = result * 31 + (this.botAdministratorRights == null ? 0 : this.botAdministratorRights.hashCode());
			return result;
		}
	}

	/**
	 * A button that opens a Web App by calling getWebAppUrl.
	**/
	public static final class KeyboardButtonTypeWebApp extends KeyboardButtonType {


		/**
		 * An HTTP URL to pass to getWebAppUrl.
		**/
		public String url;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1892220770;

		/**
		 * A button that opens a Web App by calling getWebAppUrl.
		**/
		public KeyboardButtonTypeWebApp() {}

		/**
		 * A button that opens a Web App by calling getWebAppUrl.
		 *
		 * @param url An HTTP URL to pass to getWebAppUrl.
		**/
		public KeyboardButtonTypeWebApp(String url) {
			this.url = url;
		}

		/**
		 * A button that opens a Web App by calling getWebAppUrl.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public KeyboardButtonTypeWebApp(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] urlTmp = new byte[input.readInt()];
				input.readFully(urlTmp);
				this.url = new String(urlTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return KeyboardButtonTypeWebApp.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(KeyboardButtonTypeWebApp.CONSTRUCTOR);
			if (this.url == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] urlTmp = this.url.getBytes(StandardCharsets.UTF_8);
				output.writeInt(urlTmp.length);
				output.write(urlTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			KeyboardButtonTypeWebApp keyboardButtonTypeWebApp = (KeyboardButtonTypeWebApp) o;
			if (this.url != keyboardButtonTypeWebApp.url) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.url == null ? 0 : this.url.hashCode();
		}
	}

	/**
	 * Portion of the price of a product (e.g., &quot;delivery cost&quot;,
	 * &quot;tax amount&quot;).
	**/
	public static final class LabeledPricePart extends Object {


		/**
		 * Label for this portion of the product price.
		**/
		public String label;

		/**
		 * Currency amount in the smallest units of the currency.
		**/
		public long amount;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 552789798;

		/**
		 * Portion of the price of a product (e.g., &quot;delivery cost&quot;, &quot;tax amount&quot;).
		**/
		public LabeledPricePart() {}

		/**
		 * Portion of the price of a product (e.g., &quot;delivery cost&quot;, &quot;tax amount&quot;).
		 *
		 * @param label Label for this portion of the product price.
		 * @param amount Currency amount in the smallest units of the currency.
		**/
		public LabeledPricePart(String label, long amount) {
			this.label = label;
			this.amount = amount;
		}

		/**
		 * Portion of the price of a product (e.g., &quot;delivery cost&quot;, &quot;tax amount&quot;).
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public LabeledPricePart(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] labelTmp = new byte[input.readInt()];
				input.readFully(labelTmp);
				this.label = new String(labelTmp, StandardCharsets.UTF_8);
			}
			this.amount = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return LabeledPricePart.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(LabeledPricePart.CONSTRUCTOR);
			if (this.label == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] labelTmp = this.label.getBytes(StandardCharsets.UTF_8);
				output.writeInt(labelTmp.length);
				output.write(labelTmp);
			}
			output.writeLong(this.amount);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			LabeledPricePart labeledPricePart = (LabeledPricePart) o;
			if (this.label != labeledPricePart.label) {
				return false;
			}
			if (this.amount != labeledPricePart.amount) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.amount);
			result = result * 31 + (this.label == null ? 0 : this.label.hashCode());
			return result;
		}
	}

	/**
	 * Contains information about a language pack.
	**/
	public static final class LanguagePackInfo extends Object {


		/**
		 * Unique language pack identifier.
		**/
		public String id;

		/**
		 * Identifier of a base language pack; may be empty. If a string is missed in the language pack, then it must be fetched from base language pack. Unsupported in custom language packs.
		**/
		public String baseLanguagePackId;

		/**
		 * Language name.
		**/
		public String name;

		/**
		 * Name of the language in that language.
		**/
		public String nativeName;

		/**
		 * A language code to be used to apply plural forms. See https://www.unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html for more information.
		**/
		public String pluralCode;

		/**
		 * True, if the language pack is official.
		**/
		public boolean isOfficial;

		/**
		 * True, if the language pack strings are RTL.
		**/
		public boolean isRtl;

		/**
		 * True, if the language pack is a beta language pack.
		**/
		public boolean isBeta;

		/**
		 * True, if the language pack is installed by the current user.
		**/
		public boolean isInstalled;

		/**
		 * Total number of non-deleted strings from the language pack.
		**/
		public int totalStringCount;

		/**
		 * Total number of translated strings from the language pack.
		**/
		public int translatedStringCount;

		/**
		 * Total number of non-deleted strings from the language pack available locally.
		**/
		public int localStringCount;

		/**
		 * Link to language translation interface; empty for custom local language packs.
		**/
		public String translationUrl;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 542199642;

		/**
		 * Contains information about a language pack.
		**/
		public LanguagePackInfo() {}

		/**
		 * Contains information about a language pack.
		 *
		 * @param id Unique language pack identifier.
		 * @param baseLanguagePackId Identifier of a base language pack; may be empty. If a string is missed in the language pack, then it must be fetched from base language pack. Unsupported in custom language packs.
		 * @param name Language name.
		 * @param nativeName Name of the language in that language.
		 * @param pluralCode A language code to be used to apply plural forms. See https://www.unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html for more information.
		 * @param isOfficial True, if the language pack is official.
		 * @param isRtl True, if the language pack strings are RTL.
		 * @param isBeta True, if the language pack is a beta language pack.
		 * @param isInstalled True, if the language pack is installed by the current user.
		 * @param totalStringCount Total number of non-deleted strings from the language pack.
		 * @param translatedStringCount Total number of translated strings from the language pack.
		 * @param localStringCount Total number of non-deleted strings from the language pack available locally.
		 * @param translationUrl Link to language translation interface; empty for custom local language packs.
		**/
		public LanguagePackInfo(String id,
				String baseLanguagePackId,
				String name,
				String nativeName,
				String pluralCode,
				boolean isOfficial,
				boolean isRtl,
				boolean isBeta,
				boolean isInstalled,
				int totalStringCount,
				int translatedStringCount,
				int localStringCount,
				String translationUrl) {
			this.id = id;
			this.baseLanguagePackId = baseLanguagePackId;
			this.name = name;
			this.nativeName = nativeName;
			this.pluralCode = pluralCode;
			this.isOfficial = isOfficial;
			this.isRtl = isRtl;
			this.isBeta = isBeta;
			this.isInstalled = isInstalled;
			this.totalStringCount = totalStringCount;
			this.translatedStringCount = translatedStringCount;
			this.localStringCount = localStringCount;
			this.translationUrl = translationUrl;
		}

		/**
		 * Contains information about a language pack.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public LanguagePackInfo(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] idTmp = new byte[input.readInt()];
				input.readFully(idTmp);
				this.id = new String(idTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] baseLanguagePackIdTmp = new byte[input.readInt()];
				input.readFully(baseLanguagePackIdTmp);
				this.baseLanguagePackId = new String(baseLanguagePackIdTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] nameTmp = new byte[input.readInt()];
				input.readFully(nameTmp);
				this.name = new String(nameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] nativeNameTmp = new byte[input.readInt()];
				input.readFully(nativeNameTmp);
				this.nativeName = new String(nativeNameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] pluralCodeTmp = new byte[input.readInt()];
				input.readFully(pluralCodeTmp);
				this.pluralCode = new String(pluralCodeTmp, StandardCharsets.UTF_8);
			}
			this.isOfficial = input.readBoolean();
			this.isRtl = input.readBoolean();
			this.isBeta = input.readBoolean();
			this.isInstalled = input.readBoolean();
			this.totalStringCount = input.readInt();
			this.translatedStringCount = input.readInt();
			this.localStringCount = input.readInt();
			if (input.readBoolean()) {
				byte[] translationUrlTmp = new byte[input.readInt()];
				input.readFully(translationUrlTmp);
				this.translationUrl = new String(translationUrlTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return LanguagePackInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(LanguagePackInfo.CONSTRUCTOR);
			if (this.id == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] idTmp = this.id.getBytes(StandardCharsets.UTF_8);
				output.writeInt(idTmp.length);
				output.write(idTmp);
			}
			if (this.baseLanguagePackId == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] baseLanguagePackIdTmp = this.baseLanguagePackId.getBytes(StandardCharsets.UTF_8);
				output.writeInt(baseLanguagePackIdTmp.length);
				output.write(baseLanguagePackIdTmp);
			}
			if (this.name == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nameTmp = this.name.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nameTmp.length);
				output.write(nameTmp);
			}
			if (this.nativeName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nativeNameTmp = this.nativeName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nativeNameTmp.length);
				output.write(nativeNameTmp);
			}
			if (this.pluralCode == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] pluralCodeTmp = this.pluralCode.getBytes(StandardCharsets.UTF_8);
				output.writeInt(pluralCodeTmp.length);
				output.write(pluralCodeTmp);
			}
			output.writeBoolean(this.isOfficial);
			output.writeBoolean(this.isRtl);
			output.writeBoolean(this.isBeta);
			output.writeBoolean(this.isInstalled);
			output.writeInt(this.totalStringCount);
			output.writeInt(this.translatedStringCount);
			output.writeInt(this.localStringCount);
			if (this.translationUrl == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] translationUrlTmp = this.translationUrl.getBytes(StandardCharsets.UTF_8);
				output.writeInt(translationUrlTmp.length);
				output.write(translationUrlTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			LanguagePackInfo languagePackInfo = (LanguagePackInfo) o;
			if (this.id != languagePackInfo.id) {
				return false;
			}
			if (this.baseLanguagePackId != languagePackInfo.baseLanguagePackId) {
				return false;
			}
			if (this.name != languagePackInfo.name) {
				return false;
			}
			if (this.nativeName != languagePackInfo.nativeName) {
				return false;
			}
			if (this.pluralCode != languagePackInfo.pluralCode) {
				return false;
			}
			if (this.isOfficial != languagePackInfo.isOfficial) {
				return false;
			}
			if (this.isRtl != languagePackInfo.isRtl) {
				return false;
			}
			if (this.isBeta != languagePackInfo.isBeta) {
				return false;
			}
			if (this.isInstalled != languagePackInfo.isInstalled) {
				return false;
			}
			if (this.totalStringCount != languagePackInfo.totalStringCount) {
				return false;
			}
			if (this.translatedStringCount != languagePackInfo.translatedStringCount) {
				return false;
			}
			if (this.localStringCount != languagePackInfo.localStringCount) {
				return false;
			}
			if (this.translationUrl != languagePackInfo.translationUrl) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isOfficial);
			result = result * 31 + (this.id == null ? 0 : this.id.hashCode());
			result = result * 31 + (this.baseLanguagePackId == null ? 0 : this.baseLanguagePackId.hashCode());
			result = result * 31 + (this.name == null ? 0 : this.name.hashCode());
			result = result * 31 + (this.nativeName == null ? 0 : this.nativeName.hashCode());
			result = result * 31 + (this.pluralCode == null ? 0 : this.pluralCode.hashCode());
			result = result * 31 + (this.translationUrl == null ? 0 : this.translationUrl.hashCode());
			return result;
		}
	}

	/**
	 * Represents one language pack string.
	**/
	public static final class LanguagePackString extends Object {


		/**
		 * String key.
		**/
		public String key;

		/**
		 * String value; pass null if the string needs to be taken from the built-in English language pack.
		**/
		public LanguagePackStringValue value;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1307632736;

		/**
		 * Represents one language pack string.
		**/
		public LanguagePackString() {}

		/**
		 * Represents one language pack string.
		 *
		 * @param key String key.
		 * @param value String value; pass null if the string needs to be taken from the built-in English language pack.
		**/
		public LanguagePackString(String key, LanguagePackStringValue value) {
			this.key = key;
			this.value = value;
		}

		/**
		 * Represents one language pack string.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public LanguagePackString(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] keyTmp = new byte[input.readInt()];
				input.readFully(keyTmp);
				this.key = new String(keyTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case LanguagePackStringValueOrdinary.CONSTRUCTOR: this.value = new LanguagePackStringValueOrdinary(input); break;
					case LanguagePackStringValuePluralized.CONSTRUCTOR: this.value = new LanguagePackStringValuePluralized(input); break;
					case LanguagePackStringValueDeleted.CONSTRUCTOR: this.value = new LanguagePackStringValueDeleted(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return LanguagePackString.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(LanguagePackString.CONSTRUCTOR);
			if (this.key == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] keyTmp = this.key.getBytes(StandardCharsets.UTF_8);
				output.writeInt(keyTmp.length);
				output.write(keyTmp);
			}
			if (this.value == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.value.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			LanguagePackString languagePackString = (LanguagePackString) o;
			if (this.key != languagePackString.key) {
				return false;
			}
			if (!Objects.equals(this.value, languagePackString.value)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.key == null ? 0 : this.key.hashCode();
			result = result * 31 + (this.value == null ? 0 : this.value.hashCode());
			return result;
		}
	}

	/**
	 * An ordinary language pack string.
	**/
	public static final class LanguagePackStringValueOrdinary extends LanguagePackStringValue {


		/**
		 * String value.
		**/
		public String value;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -249256352;

		/**
		 * An ordinary language pack string.
		**/
		public LanguagePackStringValueOrdinary() {}

		/**
		 * An ordinary language pack string.
		 *
		 * @param value String value.
		**/
		public LanguagePackStringValueOrdinary(String value) {
			this.value = value;
		}

		/**
		 * An ordinary language pack string.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public LanguagePackStringValueOrdinary(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] valueTmp = new byte[input.readInt()];
				input.readFully(valueTmp);
				this.value = new String(valueTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return LanguagePackStringValueOrdinary.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(LanguagePackStringValueOrdinary.CONSTRUCTOR);
			if (this.value == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] valueTmp = this.value.getBytes(StandardCharsets.UTF_8);
				output.writeInt(valueTmp.length);
				output.write(valueTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			LanguagePackStringValueOrdinary languagePackStringValueOrdinary = (LanguagePackStringValueOrdinary) o;
			if (this.value != languagePackStringValueOrdinary.value) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.value == null ? 0 : this.value.hashCode();
		}
	}

	/**
	 * A language pack string which has different forms based on the number
	 * of some object it mentions. See
	 * https://www.unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html
	 * for more information.
	**/
	public static final class LanguagePackStringValuePluralized extends LanguagePackStringValue {


		/**
		 * Value for zero objects.
		**/
		public String zeroValue;

		/**
		 * Value for one object.
		**/
		public String oneValue;

		/**
		 * Value for two objects.
		**/
		public String twoValue;

		/**
		 * Value for few objects.
		**/
		public String fewValue;

		/**
		 * Value for many objects.
		**/
		public String manyValue;

		/**
		 * Default value.
		**/
		public String otherValue;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1906840261;

		/**
		 * A language pack string which has different forms based on the number of some object it mentions. See https://www.unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html for more information.
		**/
		public LanguagePackStringValuePluralized() {}

		/**
		 * A language pack string which has different forms based on the number of some object it mentions. See https://www.unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html for more information.
		 *
		 * @param zeroValue Value for zero objects.
		 * @param oneValue Value for one object.
		 * @param twoValue Value for two objects.
		 * @param fewValue Value for few objects.
		 * @param manyValue Value for many objects.
		 * @param otherValue Default value.
		**/
		public LanguagePackStringValuePluralized(String zeroValue,
				String oneValue,
				String twoValue,
				String fewValue,
				String manyValue,
				String otherValue) {
			this.zeroValue = zeroValue;
			this.oneValue = oneValue;
			this.twoValue = twoValue;
			this.fewValue = fewValue;
			this.manyValue = manyValue;
			this.otherValue = otherValue;
		}

		/**
		 * A language pack string which has different forms based on the number of some object it mentions. See https://www.unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html for more information.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public LanguagePackStringValuePluralized(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] zeroValueTmp = new byte[input.readInt()];
				input.readFully(zeroValueTmp);
				this.zeroValue = new String(zeroValueTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] oneValueTmp = new byte[input.readInt()];
				input.readFully(oneValueTmp);
				this.oneValue = new String(oneValueTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] twoValueTmp = new byte[input.readInt()];
				input.readFully(twoValueTmp);
				this.twoValue = new String(twoValueTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] fewValueTmp = new byte[input.readInt()];
				input.readFully(fewValueTmp);
				this.fewValue = new String(fewValueTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] manyValueTmp = new byte[input.readInt()];
				input.readFully(manyValueTmp);
				this.manyValue = new String(manyValueTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] otherValueTmp = new byte[input.readInt()];
				input.readFully(otherValueTmp);
				this.otherValue = new String(otherValueTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return LanguagePackStringValuePluralized.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(LanguagePackStringValuePluralized.CONSTRUCTOR);
			if (this.zeroValue == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] zeroValueTmp = this.zeroValue.getBytes(StandardCharsets.UTF_8);
				output.writeInt(zeroValueTmp.length);
				output.write(zeroValueTmp);
			}
			if (this.oneValue == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] oneValueTmp = this.oneValue.getBytes(StandardCharsets.UTF_8);
				output.writeInt(oneValueTmp.length);
				output.write(oneValueTmp);
			}
			if (this.twoValue == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] twoValueTmp = this.twoValue.getBytes(StandardCharsets.UTF_8);
				output.writeInt(twoValueTmp.length);
				output.write(twoValueTmp);
			}
			if (this.fewValue == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] fewValueTmp = this.fewValue.getBytes(StandardCharsets.UTF_8);
				output.writeInt(fewValueTmp.length);
				output.write(fewValueTmp);
			}
			if (this.manyValue == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] manyValueTmp = this.manyValue.getBytes(StandardCharsets.UTF_8);
				output.writeInt(manyValueTmp.length);
				output.write(manyValueTmp);
			}
			if (this.otherValue == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] otherValueTmp = this.otherValue.getBytes(StandardCharsets.UTF_8);
				output.writeInt(otherValueTmp.length);
				output.write(otherValueTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			LanguagePackStringValuePluralized languagePackStringValuePluralized = (LanguagePackStringValuePluralized) o;
			if (this.zeroValue != languagePackStringValuePluralized.zeroValue) {
				return false;
			}
			if (this.oneValue != languagePackStringValuePluralized.oneValue) {
				return false;
			}
			if (this.twoValue != languagePackStringValuePluralized.twoValue) {
				return false;
			}
			if (this.fewValue != languagePackStringValuePluralized.fewValue) {
				return false;
			}
			if (this.manyValue != languagePackStringValuePluralized.manyValue) {
				return false;
			}
			if (this.otherValue != languagePackStringValuePluralized.otherValue) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.zeroValue == null ? 0 : this.zeroValue.hashCode();
			result = result * 31 + (this.oneValue == null ? 0 : this.oneValue.hashCode());
			result = result * 31 + (this.twoValue == null ? 0 : this.twoValue.hashCode());
			result = result * 31 + (this.fewValue == null ? 0 : this.fewValue.hashCode());
			result = result * 31 + (this.manyValue == null ? 0 : this.manyValue.hashCode());
			result = result * 31 + (this.otherValue == null ? 0 : this.otherValue.hashCode());
			return result;
		}
	}

	/**
	 * A deleted language pack string, the value must be taken from the
	 * built-in English language pack.
	**/
	public static final class LanguagePackStringValueDeleted extends LanguagePackStringValue {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1834792698;

		/**
		 * A deleted language pack string, the value must be taken from the built-in English language pack.
		**/
		public LanguagePackStringValueDeleted() {}

		/**
		 * A deleted language pack string, the value must be taken from the built-in English language pack.
		 *
		**/

		/**
		 * A deleted language pack string, the value must be taken from the built-in English language pack.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public LanguagePackStringValueDeleted(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return LanguagePackStringValueDeleted.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(LanguagePackStringValueDeleted.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return LanguagePackStringValueDeleted.CONSTRUCTOR;
		}
	}

	/**
	 * Contains a list of language pack strings.
	**/
	public static final class LanguagePackStrings extends Object {


		/**
		 * A list of language pack strings.
		**/
		public LanguagePackString[] strings;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1172082922;

		/**
		 * Contains a list of language pack strings.
		**/
		public LanguagePackStrings() {}

		/**
		 * Contains a list of language pack strings.
		 *
		 * @param strings A list of language pack strings.
		**/
		public LanguagePackStrings(LanguagePackString[] strings) {
			this.strings = strings;
		}

		/**
		 * Contains a list of language pack strings.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public LanguagePackStrings(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.strings = new LanguagePackString[input.readInt()];
				for (int i = 0; i < this.strings.length; i++) {
					if (LanguagePackString.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.strings[i] = new LanguagePackString(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return LanguagePackStrings.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(LanguagePackStrings.CONSTRUCTOR);
			if (this.strings == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.strings.length);
				for (int i = 0; i < this.strings.length; i++) {
					this.strings[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			LanguagePackStrings languagePackStrings = (LanguagePackStrings) o;
			if (!Arrays.equals(this.strings, languagePackStrings.strings)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.strings);
		}
	}

	/**
	 * Represents a local file.
	**/
	public static final class LocalFile extends Object {


		/**
		 * Local path to the locally available file part; may be empty.
		**/
		public String path;

		/**
		 * True, if it is possible to download or generate the file.
		**/
		public boolean canBeDownloaded;

		/**
		 * True, if the file can be deleted.
		**/
		public boolean canBeDeleted;

		/**
		 * True, if the file is currently being downloaded (or a local copy is being generated by some other means).
		**/
		public boolean isDownloadingActive;

		/**
		 * True, if the local copy is fully available.
		**/
		public boolean isDownloadingCompleted;

		/**
		 * Download will be started from this offset. downloadedPrefixSize is calculated from this offset.
		**/
		public long downloadOffset;

		/**
		 * If isDownloadingCompleted is false, then only some prefix of the file starting from downloadOffset is ready to be read. downloadedPrefixSize is the size of that prefix in bytes.
		**/
		public long downloadedPrefixSize;

		/**
		 * Total downloaded file size, in bytes. Can be used only for calculating download progress. The actual file size may be bigger, and some parts of it may contain garbage.
		**/
		public long downloadedSize;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1562732153;

		/**
		 * Represents a local file.
		**/
		public LocalFile() {}

		/**
		 * Represents a local file.
		 *
		 * @param path Local path to the locally available file part; may be empty.
		 * @param canBeDownloaded True, if it is possible to download or generate the file.
		 * @param canBeDeleted True, if the file can be deleted.
		 * @param isDownloadingActive True, if the file is currently being downloaded (or a local copy is being generated by some other means).
		 * @param isDownloadingCompleted True, if the local copy is fully available.
		 * @param downloadOffset Download will be started from this offset. downloadedPrefixSize is calculated from this offset.
		 * @param downloadedPrefixSize If isDownloadingCompleted is false, then only some prefix of the file starting from downloadOffset is ready to be read. downloadedPrefixSize is the size of that prefix in bytes.
		 * @param downloadedSize Total downloaded file size, in bytes. Can be used only for calculating download progress. The actual file size may be bigger, and some parts of it may contain garbage.
		**/
		public LocalFile(String path,
				boolean canBeDownloaded,
				boolean canBeDeleted,
				boolean isDownloadingActive,
				boolean isDownloadingCompleted,
				long downloadOffset,
				long downloadedPrefixSize,
				long downloadedSize) {
			this.path = path;
			this.canBeDownloaded = canBeDownloaded;
			this.canBeDeleted = canBeDeleted;
			this.isDownloadingActive = isDownloadingActive;
			this.isDownloadingCompleted = isDownloadingCompleted;
			this.downloadOffset = downloadOffset;
			this.downloadedPrefixSize = downloadedPrefixSize;
			this.downloadedSize = downloadedSize;
		}

		/**
		 * Represents a local file.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public LocalFile(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] pathTmp = new byte[input.readInt()];
				input.readFully(pathTmp);
				this.path = new String(pathTmp, StandardCharsets.UTF_8);
			}
			this.canBeDownloaded = input.readBoolean();
			this.canBeDeleted = input.readBoolean();
			this.isDownloadingActive = input.readBoolean();
			this.isDownloadingCompleted = input.readBoolean();
			this.downloadOffset = input.readLong();
			this.downloadedPrefixSize = input.readLong();
			this.downloadedSize = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return LocalFile.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(LocalFile.CONSTRUCTOR);
			if (this.path == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] pathTmp = this.path.getBytes(StandardCharsets.UTF_8);
				output.writeInt(pathTmp.length);
				output.write(pathTmp);
			}
			output.writeBoolean(this.canBeDownloaded);
			output.writeBoolean(this.canBeDeleted);
			output.writeBoolean(this.isDownloadingActive);
			output.writeBoolean(this.isDownloadingCompleted);
			output.writeLong(this.downloadOffset);
			output.writeLong(this.downloadedPrefixSize);
			output.writeLong(this.downloadedSize);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			LocalFile localFile = (LocalFile) o;
			if (this.path != localFile.path) {
				return false;
			}
			if (this.canBeDownloaded != localFile.canBeDownloaded) {
				return false;
			}
			if (this.canBeDeleted != localFile.canBeDeleted) {
				return false;
			}
			if (this.isDownloadingActive != localFile.isDownloadingActive) {
				return false;
			}
			if (this.isDownloadingCompleted != localFile.isDownloadingCompleted) {
				return false;
			}
			if (this.downloadOffset != localFile.downloadOffset) {
				return false;
			}
			if (this.downloadedPrefixSize != localFile.downloadedPrefixSize) {
				return false;
			}
			if (this.downloadedSize != localFile.downloadedSize) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.canBeDownloaded);
			result = result * 31 + (this.path == null ? 0 : this.path.hashCode());
			return result;
		}
	}

	/**
	 * Contains information about the current localization target.
	**/
	public static final class LocalizationTargetInfo extends Object {


		/**
		 * List of available language packs for this application.
		**/
		public LanguagePackInfo[] languagePacks;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2048670809;

		/**
		 * Contains information about the current localization target.
		**/
		public LocalizationTargetInfo() {}

		/**
		 * Contains information about the current localization target.
		 *
		 * @param languagePacks List of available language packs for this application.
		**/
		public LocalizationTargetInfo(LanguagePackInfo[] languagePacks) {
			this.languagePacks = languagePacks;
		}

		/**
		 * Contains information about the current localization target.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public LocalizationTargetInfo(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.languagePacks = new LanguagePackInfo[input.readInt()];
				for (int i = 0; i < this.languagePacks.length; i++) {
					if (LanguagePackInfo.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.languagePacks[i] = new LanguagePackInfo(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return LocalizationTargetInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(LocalizationTargetInfo.CONSTRUCTOR);
			if (this.languagePacks == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.languagePacks.length);
				for (int i = 0; i < this.languagePacks.length; i++) {
					this.languagePacks[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			LocalizationTargetInfo localizationTargetInfo = (LocalizationTargetInfo) o;
			if (!Arrays.equals(this.languagePacks, localizationTargetInfo.languagePacks)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.languagePacks);
		}
	}

	/**
	 * Describes a location on planet Earth.
	**/
	public static final class Location extends Object {


		/**
		 * Latitude of the location in degrees; as defined by the sender.
		**/
		public double latitude;

		/**
		 * Longitude of the location, in degrees; as defined by the sender.
		**/
		public double longitude;

		/**
		 * The estimated horizontal accuracy of the location, in meters; as defined by the sender. 0 if unknown.
		**/
		public double horizontalAccuracy;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -443392141;

		/**
		 * Describes a location on planet Earth.
		**/
		public Location() {}

		/**
		 * Describes a location on planet Earth.
		 *
		 * @param latitude Latitude of the location in degrees; as defined by the sender.
		 * @param longitude Longitude of the location, in degrees; as defined by the sender.
		 * @param horizontalAccuracy The estimated horizontal accuracy of the location, in meters; as defined by the sender. 0 if unknown.
		**/
		public Location(double latitude, double longitude, double horizontalAccuracy) {
			this.latitude = latitude;
			this.longitude = longitude;
			this.horizontalAccuracy = horizontalAccuracy;
		}

		/**
		 * Describes a location on planet Earth.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public Location(DataInput input) throws IOException {
			this.latitude = input.readDouble();
			this.longitude = input.readDouble();
			this.horizontalAccuracy = input.readDouble();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return Location.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(Location.CONSTRUCTOR);
			output.writeDouble(this.latitude);
			output.writeDouble(this.longitude);
			output.writeDouble(this.horizontalAccuracy);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			Location location = (Location) o;
			if (this.latitude != location.latitude) {
				return false;
			}
			if (this.longitude != location.longitude) {
				return false;
			}
			if (this.horizontalAccuracy != location.horizontalAccuracy) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Double.hashCode(this.latitude);
			return result;
		}
	}

	/**
	 * The log is written to stderr or an OS specific log.
	**/
	public static final class LogStreamDefault extends LogStream {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1390581436;

		/**
		 * The log is written to stderr or an OS specific log.
		**/
		public LogStreamDefault() {}

		/**
		 * The log is written to stderr or an OS specific log.
		 *
		**/

		/**
		 * The log is written to stderr or an OS specific log.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public LogStreamDefault(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return LogStreamDefault.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(LogStreamDefault.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return LogStreamDefault.CONSTRUCTOR;
		}
	}

	/**
	 * The log is written to a file.
	**/
	public static final class LogStreamFile extends LogStream {


		/**
		 * Path to the file to where the internal TDLib log will be written.
		**/
		public String path;

		/**
		 * The maximum size of the file to where the internal TDLib log is written before the file will automatically be rotated, in bytes.
		**/
		public long maxFileSize;

		/**
		 * Pass true to additionally redirect stderr to the log file. Ignored on Windows.
		**/
		public boolean redirectStderr;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1532136933;

		/**
		 * The log is written to a file.
		**/
		public LogStreamFile() {}

		/**
		 * The log is written to a file.
		 *
		 * @param path Path to the file to where the internal TDLib log will be written.
		 * @param maxFileSize The maximum size of the file to where the internal TDLib log is written before the file will automatically be rotated, in bytes.
		 * @param redirectStderr Pass true to additionally redirect stderr to the log file. Ignored on Windows.
		**/
		public LogStreamFile(String path, long maxFileSize, boolean redirectStderr) {
			this.path = path;
			this.maxFileSize = maxFileSize;
			this.redirectStderr = redirectStderr;
		}

		/**
		 * The log is written to a file.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public LogStreamFile(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] pathTmp = new byte[input.readInt()];
				input.readFully(pathTmp);
				this.path = new String(pathTmp, StandardCharsets.UTF_8);
			}
			this.maxFileSize = input.readLong();
			this.redirectStderr = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return LogStreamFile.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(LogStreamFile.CONSTRUCTOR);
			if (this.path == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] pathTmp = this.path.getBytes(StandardCharsets.UTF_8);
				output.writeInt(pathTmp.length);
				output.write(pathTmp);
			}
			output.writeLong(this.maxFileSize);
			output.writeBoolean(this.redirectStderr);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			LogStreamFile logStreamFile = (LogStreamFile) o;
			if (this.path != logStreamFile.path) {
				return false;
			}
			if (this.maxFileSize != logStreamFile.maxFileSize) {
				return false;
			}
			if (this.redirectStderr != logStreamFile.redirectStderr) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.maxFileSize);
			result = result * 31 + (this.path == null ? 0 : this.path.hashCode());
			return result;
		}
	}

	/**
	 * The log is written nowhere.
	**/
	public static final class LogStreamEmpty extends LogStream {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -499912244;

		/**
		 * The log is written nowhere.
		**/
		public LogStreamEmpty() {}

		/**
		 * The log is written nowhere.
		 *
		**/

		/**
		 * The log is written nowhere.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public LogStreamEmpty(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return LogStreamEmpty.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(LogStreamEmpty.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return LogStreamEmpty.CONSTRUCTOR;
		}
	}

	/**
	 * Contains a list of available TDLib internal log tags.
	**/
	public static final class LogTags extends Object {


		/**
		 * List of log tags.
		**/
		public String[] tags;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1604930601;

		/**
		 * Contains a list of available TDLib internal log tags.
		**/
		public LogTags() {}

		/**
		 * Contains a list of available TDLib internal log tags.
		 *
		 * @param tags List of log tags.
		**/
		public LogTags(String[] tags) {
			this.tags = tags;
		}

		/**
		 * Contains a list of available TDLib internal log tags.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public LogTags(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.tags = new String[input.readInt()];
				for (int i = 0; i < this.tags.length; i++) {
					byte[] tagsTmp = new byte[input.readInt()];
					input.readFully(tagsTmp);
					this.tags[i] = new String(tagsTmp, StandardCharsets.UTF_8);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return LogTags.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(LogTags.CONSTRUCTOR);
			if (this.tags == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.tags.length);
				for (int i = 0; i < this.tags.length; i++) {
					byte[] tagsTmp = this.tags[i].getBytes(StandardCharsets.UTF_8);
					output.writeInt(tagsTmp.length);
					output.write(tagsTmp);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			LogTags logTags = (LogTags) o;
			if (!Arrays.equals(this.tags, logTags.tags)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.tags);
		}
	}

	/**
	 * Contains a TDLib internal log verbosity level.
	**/
	public static final class LogVerbosityLevel extends Object {


		/**
		 * Log verbosity level.
		**/
		public int verbosityLevel;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1734624234;

		/**
		 * Contains a TDLib internal log verbosity level.
		**/
		public LogVerbosityLevel() {}

		/**
		 * Contains a TDLib internal log verbosity level.
		 *
		 * @param verbosityLevel Log verbosity level.
		**/
		public LogVerbosityLevel(int verbosityLevel) {
			this.verbosityLevel = verbosityLevel;
		}

		/**
		 * Contains a TDLib internal log verbosity level.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public LogVerbosityLevel(DataInput input) throws IOException {
			this.verbosityLevel = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return LogVerbosityLevel.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(LogVerbosityLevel.CONSTRUCTOR);
			output.writeInt(this.verbosityLevel);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			LogVerbosityLevel logVerbosityLevel = (LogVerbosityLevel) o;
			if (this.verbosityLevel != logVerbosityLevel.verbosityLevel) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.verbosityLevel);
		}
	}

	/**
	 * An HTTP URL needs to be open.
	**/
	public static final class LoginUrlInfoOpen extends LoginUrlInfo {


		/**
		 * The URL to open.
		**/
		public String url;

		/**
		 * True, if there is no need to show an ordinary open URL confirmation.
		**/
		public boolean skipConfirmation;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 837282306;

		/**
		 * An HTTP URL needs to be open.
		**/
		public LoginUrlInfoOpen() {}

		/**
		 * An HTTP URL needs to be open.
		 *
		 * @param url The URL to open.
		 * @param skipConfirmation True, if there is no need to show an ordinary open URL confirmation.
		**/
		public LoginUrlInfoOpen(String url, boolean skipConfirmation) {
			this.url = url;
			this.skipConfirmation = skipConfirmation;
		}

		/**
		 * An HTTP URL needs to be open.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public LoginUrlInfoOpen(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] urlTmp = new byte[input.readInt()];
				input.readFully(urlTmp);
				this.url = new String(urlTmp, StandardCharsets.UTF_8);
			}
			this.skipConfirmation = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return LoginUrlInfoOpen.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(LoginUrlInfoOpen.CONSTRUCTOR);
			if (this.url == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] urlTmp = this.url.getBytes(StandardCharsets.UTF_8);
				output.writeInt(urlTmp.length);
				output.write(urlTmp);
			}
			output.writeBoolean(this.skipConfirmation);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			LoginUrlInfoOpen loginUrlInfoOpen = (LoginUrlInfoOpen) o;
			if (this.url != loginUrlInfoOpen.url) {
				return false;
			}
			if (this.skipConfirmation != loginUrlInfoOpen.skipConfirmation) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.skipConfirmation);
			result = result * 31 + (this.url == null ? 0 : this.url.hashCode());
			return result;
		}
	}

	/**
	 * An authorization confirmation dialog needs to be shown to the user.
	**/
	public static final class LoginUrlInfoRequestConfirmation extends LoginUrlInfo {


		/**
		 * An HTTP URL to be opened.
		**/
		public String url;

		/**
		 * A domain of the URL.
		**/
		public String domain;

		/**
		 * User identifier of a bot linked with the website.
		**/
		public long botUserId;

		/**
		 * True, if the user must be asked for the permission to the bot to send them messages.
		**/
		public boolean requestWriteAccess;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2128290863;

		/**
		 * An authorization confirmation dialog needs to be shown to the user.
		**/
		public LoginUrlInfoRequestConfirmation() {}

		/**
		 * An authorization confirmation dialog needs to be shown to the user.
		 *
		 * @param url An HTTP URL to be opened.
		 * @param domain A domain of the URL.
		 * @param botUserId User identifier of a bot linked with the website.
		 * @param requestWriteAccess True, if the user must be asked for the permission to the bot to send them messages.
		**/
		public LoginUrlInfoRequestConfirmation(String url,
				String domain,
				long botUserId,
				boolean requestWriteAccess) {
			this.url = url;
			this.domain = domain;
			this.botUserId = botUserId;
			this.requestWriteAccess = requestWriteAccess;
		}

		/**
		 * An authorization confirmation dialog needs to be shown to the user.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public LoginUrlInfoRequestConfirmation(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] urlTmp = new byte[input.readInt()];
				input.readFully(urlTmp);
				this.url = new String(urlTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] domainTmp = new byte[input.readInt()];
				input.readFully(domainTmp);
				this.domain = new String(domainTmp, StandardCharsets.UTF_8);
			}
			this.botUserId = input.readLong();
			this.requestWriteAccess = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return LoginUrlInfoRequestConfirmation.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(LoginUrlInfoRequestConfirmation.CONSTRUCTOR);
			if (this.url == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] urlTmp = this.url.getBytes(StandardCharsets.UTF_8);
				output.writeInt(urlTmp.length);
				output.write(urlTmp);
			}
			if (this.domain == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] domainTmp = this.domain.getBytes(StandardCharsets.UTF_8);
				output.writeInt(domainTmp.length);
				output.write(domainTmp);
			}
			output.writeLong(this.botUserId);
			output.writeBoolean(this.requestWriteAccess);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			LoginUrlInfoRequestConfirmation loginUrlInfoRequestConfirmation = (LoginUrlInfoRequestConfirmation) o;
			if (this.url != loginUrlInfoRequestConfirmation.url) {
				return false;
			}
			if (this.domain != loginUrlInfoRequestConfirmation.domain) {
				return false;
			}
			if (this.botUserId != loginUrlInfoRequestConfirmation.botUserId) {
				return false;
			}
			if (this.requestWriteAccess != loginUrlInfoRequestConfirmation.requestWriteAccess) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.botUserId);
			result = result * 31 + (this.url == null ? 0 : this.url.hashCode());
			result = result * 31 + (this.domain == null ? 0 : this.domain.hashCode());
			return result;
		}
	}

	/**
	 * The mask is placed relatively to the forehead.
	**/
	public static final class MaskPointForehead extends MaskPoint {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1027512005;

		/**
		 * The mask is placed relatively to the forehead.
		**/
		public MaskPointForehead() {}

		/**
		 * The mask is placed relatively to the forehead.
		 *
		**/

		/**
		 * The mask is placed relatively to the forehead.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MaskPointForehead(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MaskPointForehead.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MaskPointForehead.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return MaskPointForehead.CONSTRUCTOR;
		}
	}

	/**
	 * The mask is placed relatively to the eyes.
	**/
	public static final class MaskPointEyes extends MaskPoint {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1748310861;

		/**
		 * The mask is placed relatively to the eyes.
		**/
		public MaskPointEyes() {}

		/**
		 * The mask is placed relatively to the eyes.
		 *
		**/

		/**
		 * The mask is placed relatively to the eyes.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MaskPointEyes(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MaskPointEyes.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MaskPointEyes.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return MaskPointEyes.CONSTRUCTOR;
		}
	}

	/**
	 * The mask is placed relatively to the mouth.
	**/
	public static final class MaskPointMouth extends MaskPoint {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 411773406;

		/**
		 * The mask is placed relatively to the mouth.
		**/
		public MaskPointMouth() {}

		/**
		 * The mask is placed relatively to the mouth.
		 *
		**/

		/**
		 * The mask is placed relatively to the mouth.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MaskPointMouth(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MaskPointMouth.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MaskPointMouth.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return MaskPointMouth.CONSTRUCTOR;
		}
	}

	/**
	 * The mask is placed relatively to the chin.
	**/
	public static final class MaskPointChin extends MaskPoint {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 534995335;

		/**
		 * The mask is placed relatively to the chin.
		**/
		public MaskPointChin() {}

		/**
		 * The mask is placed relatively to the chin.
		 *
		**/

		/**
		 * The mask is placed relatively to the chin.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MaskPointChin(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MaskPointChin.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MaskPointChin.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return MaskPointChin.CONSTRUCTOR;
		}
	}

	/**
	 * Position on a photo where a mask is placed.
	**/
	public static final class MaskPosition extends Object {


		/**
		 * Part of the face, relative to which the mask is placed.
		**/
		public MaskPoint point;

		/**
		 * Shift by X-axis measured in widths of the mask scaled to the face size, from left to right. (For example, -1.0 will place the mask just to the left of the default mask position.)
		**/
		public double xShift;

		/**
		 * Shift by Y-axis measured in heights of the mask scaled to the face size, from top to bottom. (For example, 1.0 will place the mask just below the default mask position.)
		**/
		public double yShift;

		/**
		 * Mask scaling coefficient. (For example, 2.0 means a doubled size.)
		**/
		public double scale;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2097433026;

		/**
		 * Position on a photo where a mask is placed.
		**/
		public MaskPosition() {}

		/**
		 * Position on a photo where a mask is placed.
		 *
		 * @param point Part of the face, relative to which the mask is placed.
		 * @param xShift Shift by X-axis measured in widths of the mask scaled to the face size, from left to right. (For example, -1.0 will place the mask just to the left of the default mask position.)
		 * @param yShift Shift by Y-axis measured in heights of the mask scaled to the face size, from top to bottom. (For example, 1.0 will place the mask just below the default mask position.)
		 * @param scale Mask scaling coefficient. (For example, 2.0 means a doubled size.)
		**/
		public MaskPosition(MaskPoint point, double xShift, double yShift, double scale) {
			this.point = point;
			this.xShift = xShift;
			this.yShift = yShift;
			this.scale = scale;
		}

		/**
		 * Position on a photo where a mask is placed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MaskPosition(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case MaskPointForehead.CONSTRUCTOR: this.point = new MaskPointForehead(input); break;
					case MaskPointEyes.CONSTRUCTOR: this.point = new MaskPointEyes(input); break;
					case MaskPointMouth.CONSTRUCTOR: this.point = new MaskPointMouth(input); break;
					case MaskPointChin.CONSTRUCTOR: this.point = new MaskPointChin(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.xShift = input.readDouble();
			this.yShift = input.readDouble();
			this.scale = input.readDouble();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MaskPosition.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MaskPosition.CONSTRUCTOR);
			if (this.point == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.point.serialize(output);
			}
			output.writeDouble(this.xShift);
			output.writeDouble(this.yShift);
			output.writeDouble(this.scale);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MaskPosition maskPosition = (MaskPosition) o;
			if (!Objects.equals(this.point, maskPosition.point)) {
				return false;
			}
			if (this.xShift != maskPosition.xShift) {
				return false;
			}
			if (this.yShift != maskPosition.yShift) {
				return false;
			}
			if (this.scale != maskPosition.scale) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Double.hashCode(this.xShift);
			result = result * 31 + (this.point == null ? 0 : this.point.hashCode());
			return result;
		}
	}

	/**
	 * Contains memory statistics.
	**/
	public static final class MemoryStatistics extends Object {


		/**
		 * Memory statistics in an unspecified human-readable format.
		**/
		public String statistics;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1925890898;

		/**
		 * Contains memory statistics.
		**/
		public MemoryStatistics() {}

		/**
		 * Contains memory statistics.
		 *
		 * @param statistics Memory statistics in an unspecified human-readable format.
		**/
		public MemoryStatistics(String statistics) {
			this.statistics = statistics;
		}

		/**
		 * Contains memory statistics.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MemoryStatistics(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] statisticsTmp = new byte[input.readInt()];
				input.readFully(statisticsTmp);
				this.statistics = new String(statisticsTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MemoryStatistics.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MemoryStatistics.CONSTRUCTOR);
			if (this.statistics == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] statisticsTmp = this.statistics.getBytes(StandardCharsets.UTF_8);
				output.writeInt(statisticsTmp.length);
				output.write(statisticsTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MemoryStatistics memoryStatistics = (MemoryStatistics) o;
			if (this.statistics != memoryStatistics.statistics) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.statistics == null ? 0 : this.statistics.hashCode();
		}
	}

	/**
	 * Describes a message.
	**/
	public static final class Message extends Object {


		/**
		 * Message identifier; unique for the chat to which the message belongs.
		**/
		public long id;

		/**
		 * Identifier of the sender of the message.
		**/
		public MessageSender senderId;

		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * The sending state of the message; may be null.
		**/
		public MessageSendingState sendingState;

		/**
		 * The scheduling state of the message; may be null.
		**/
		public MessageSchedulingState schedulingState;

		/**
		 * True, if the message is outgoing.
		**/
		public boolean isOutgoing;

		/**
		 * True, if the message is pinned.
		**/
		public boolean isPinned;

		/**
		 * True, if the message can be edited. For live location and poll messages this fields shows whether editMessageLiveLocation or stopPoll can be used with this message by the application.
		**/
		public boolean canBeEdited;

		/**
		 * True, if the message can be forwarded.
		**/
		public boolean canBeForwarded;

		/**
		 * True, if content of the message can be saved locally or copied.
		**/
		public boolean canBeSaved;

		/**
		 * True, if the message can be deleted only for the current user while other users will continue to see it.
		**/
		public boolean canBeDeletedOnlyForSelf;

		/**
		 * True, if the message can be deleted for all users.
		**/
		public boolean canBeDeletedForAllUsers;

		/**
		 * True, if the list of added reactions is available through getMessageAddedReactions.
		**/
		public boolean canGetAddedReactions;

		/**
		 * True, if the message statistics are available through getMessageStatistics.
		**/
		public boolean canGetStatistics;

		/**
		 * True, if information about the message thread is available through getMessageThread and getMessageThreadHistory.
		**/
		public boolean canGetMessageThread;

		/**
		 * True, if chat members already viewed the message can be received through getMessageViewers.
		**/
		public boolean canGetViewers;

		/**
		 * True, if media timestamp links can be generated for media timestamp entities in the message text, caption or web page description through getMessageLink.
		**/
		public boolean canGetMediaTimestampLinks;

		/**
		 * True, if reactions on the message can be reported through reportMessageReactions.
		**/
		public boolean canReportReactions;

		/**
		 * True, if media timestamp entities refers to a media in this message as opposed to a media in the replied message.
		**/
		public boolean hasTimestampedMedia;

		/**
		 * True, if the message is a channel post. All messages to channels are channel posts, all other messages are not channel posts.
		**/
		public boolean isChannelPost;

		/**
		 * True, if the message is a forum topic message.
		**/
		public boolean isTopicMessage;

		/**
		 * True, if the message contains an unread mention for the current user.
		**/
		public boolean containsUnreadMention;

		/**
		 * Point in time (Unix timestamp) when the message was sent.
		**/
		public int date;

		/**
		 * Point in time (Unix timestamp) when the message was last edited.
		**/
		public int editDate;

		/**
		 * Information about the initial message sender; may be null.
		**/
		public MessageForwardInfo forwardInfo;

		/**
		 * Information about interactions with the message; may be null.
		**/
		public MessageInteractionInfo interactionInfo;

		/**
		 * Information about unread reactions added to the message.
		**/
		public UnreadReaction[] unreadReactions;

		/**
		 * If non-zero, the identifier of the chat to which the replied message belongs; Currently, only messages in the Replies chat can have different replyInChatId and chatId.
		**/
		public long replyInChatId;

		/**
		 * If non-zero, the identifier of the message this message is replying to; can be the identifier of a deleted message.
		**/
		public long replyToMessageId;

		/**
		 * If non-zero, the identifier of the message thread the message belongs to; unique within the chat to which the message belongs.
		**/
		public long messageThreadId;

		/**
		 * The message&#039;s self-destruct time, in seconds; 0 if none. TDLib will send updateDeleteMessages or updateMessageContent once the time expires.
		**/
		public int selfDestructTime;

		/**
		 * Time left before the message self-destruct timer expires, in seconds. If the self-destruct timer isn&#039;t started yet, equals to the value of the selfDestructTime field.
		**/
		public double selfDestructIn;

		/**
		 * Time left before the message will be automatically deleted by messageAutoDeleteTime setting of the chat, in seconds; 0 if never. TDLib will send updateDeleteMessages or updateMessageContent once the time expires.
		**/
		public double autoDeleteIn;

		/**
		 * If non-zero, the user identifier of the bot through which this message was sent.
		**/
		public long viaBotUserId;

		/**
		 * For channel posts and anonymous group messages, optional author signature.
		**/
		public String authorSignature;

		/**
		 * Unique identifier of an album this message belongs to. Only audios, documents, photos and videos can be grouped together in albums.
		**/
		public long mediaAlbumId;

		/**
		 * If non-empty, contains a human-readable description of the reason why access to this message must be restricted.
		**/
		public String restrictionReason;

		/**
		 * Content of the message.
		**/
		public MessageContent content;

		/**
		 * Reply markup for the message; may be null.
		**/
		public ReplyMarkup replyMarkup;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 991863559;

		/**
		 * Describes a message.
		**/
		public Message() {}

		/**
		 * Describes a message.
		 *
		 * @param id Message identifier; unique for the chat to which the message belongs.
		 * @param senderId Identifier of the sender of the message.
		 * @param chatId Chat identifier.
		 * @param sendingState The sending state of the message; may be null.
		 * @param schedulingState The scheduling state of the message; may be null.
		 * @param isOutgoing True, if the message is outgoing.
		 * @param isPinned True, if the message is pinned.
		 * @param canBeEdited True, if the message can be edited. For live location and poll messages this fields shows whether editMessageLiveLocation or stopPoll can be used with this message by the application.
		 * @param canBeForwarded True, if the message can be forwarded.
		 * @param canBeSaved True, if content of the message can be saved locally or copied.
		 * @param canBeDeletedOnlyForSelf True, if the message can be deleted only for the current user while other users will continue to see it.
		 * @param canBeDeletedForAllUsers True, if the message can be deleted for all users.
		 * @param canGetAddedReactions True, if the list of added reactions is available through getMessageAddedReactions.
		 * @param canGetStatistics True, if the message statistics are available through getMessageStatistics.
		 * @param canGetMessageThread True, if information about the message thread is available through getMessageThread and getMessageThreadHistory.
		 * @param canGetViewers True, if chat members already viewed the message can be received through getMessageViewers.
		 * @param canGetMediaTimestampLinks True, if media timestamp links can be generated for media timestamp entities in the message text, caption or web page description through getMessageLink.
		 * @param canReportReactions True, if reactions on the message can be reported through reportMessageReactions.
		 * @param hasTimestampedMedia True, if media timestamp entities refers to a media in this message as opposed to a media in the replied message.
		 * @param isChannelPost True, if the message is a channel post. All messages to channels are channel posts, all other messages are not channel posts.
		 * @param isTopicMessage True, if the message is a forum topic message.
		 * @param containsUnreadMention True, if the message contains an unread mention for the current user.
		 * @param date Point in time (Unix timestamp) when the message was sent.
		 * @param editDate Point in time (Unix timestamp) when the message was last edited.
		 * @param forwardInfo Information about the initial message sender; may be null.
		 * @param interactionInfo Information about interactions with the message; may be null.
		 * @param unreadReactions Information about unread reactions added to the message.
		 * @param replyInChatId If non-zero, the identifier of the chat to which the replied message belongs; Currently, only messages in the Replies chat can have different replyInChatId and chatId.
		 * @param replyToMessageId If non-zero, the identifier of the message this message is replying to; can be the identifier of a deleted message.
		 * @param messageThreadId If non-zero, the identifier of the message thread the message belongs to; unique within the chat to which the message belongs.
		 * @param selfDestructTime The message&#039;s self-destruct time, in seconds; 0 if none. TDLib will send updateDeleteMessages or updateMessageContent once the time expires.
		 * @param selfDestructIn Time left before the message self-destruct timer expires, in seconds. If the self-destruct timer isn&#039;t started yet, equals to the value of the selfDestructTime field.
		 * @param autoDeleteIn Time left before the message will be automatically deleted by messageAutoDeleteTime setting of the chat, in seconds; 0 if never. TDLib will send updateDeleteMessages or updateMessageContent once the time expires.
		 * @param viaBotUserId If non-zero, the user identifier of the bot through which this message was sent.
		 * @param authorSignature For channel posts and anonymous group messages, optional author signature.
		 * @param mediaAlbumId Unique identifier of an album this message belongs to. Only audios, documents, photos and videos can be grouped together in albums.
		 * @param restrictionReason If non-empty, contains a human-readable description of the reason why access to this message must be restricted.
		 * @param content Content of the message.
		 * @param replyMarkup Reply markup for the message; may be null.
		**/
		public Message(long id,
				MessageSender senderId,
				long chatId,
				MessageSendingState sendingState,
				MessageSchedulingState schedulingState,
				boolean isOutgoing,
				boolean isPinned,
				boolean canBeEdited,
				boolean canBeForwarded,
				boolean canBeSaved,
				boolean canBeDeletedOnlyForSelf,
				boolean canBeDeletedForAllUsers,
				boolean canGetAddedReactions,
				boolean canGetStatistics,
				boolean canGetMessageThread,
				boolean canGetViewers,
				boolean canGetMediaTimestampLinks,
				boolean canReportReactions,
				boolean hasTimestampedMedia,
				boolean isChannelPost,
				boolean isTopicMessage,
				boolean containsUnreadMention,
				int date,
				int editDate,
				MessageForwardInfo forwardInfo,
				MessageInteractionInfo interactionInfo,
				UnreadReaction[] unreadReactions,
				long replyInChatId,
				long replyToMessageId,
				long messageThreadId,
				int selfDestructTime,
				double selfDestructIn,
				double autoDeleteIn,
				long viaBotUserId,
				String authorSignature,
				long mediaAlbumId,
				String restrictionReason,
				MessageContent content,
				ReplyMarkup replyMarkup) {
			this.id = id;
			this.senderId = senderId;
			this.chatId = chatId;
			this.sendingState = sendingState;
			this.schedulingState = schedulingState;
			this.isOutgoing = isOutgoing;
			this.isPinned = isPinned;
			this.canBeEdited = canBeEdited;
			this.canBeForwarded = canBeForwarded;
			this.canBeSaved = canBeSaved;
			this.canBeDeletedOnlyForSelf = canBeDeletedOnlyForSelf;
			this.canBeDeletedForAllUsers = canBeDeletedForAllUsers;
			this.canGetAddedReactions = canGetAddedReactions;
			this.canGetStatistics = canGetStatistics;
			this.canGetMessageThread = canGetMessageThread;
			this.canGetViewers = canGetViewers;
			this.canGetMediaTimestampLinks = canGetMediaTimestampLinks;
			this.canReportReactions = canReportReactions;
			this.hasTimestampedMedia = hasTimestampedMedia;
			this.isChannelPost = isChannelPost;
			this.isTopicMessage = isTopicMessage;
			this.containsUnreadMention = containsUnreadMention;
			this.date = date;
			this.editDate = editDate;
			this.forwardInfo = forwardInfo;
			this.interactionInfo = interactionInfo;
			this.unreadReactions = unreadReactions;
			this.replyInChatId = replyInChatId;
			this.replyToMessageId = replyToMessageId;
			this.messageThreadId = messageThreadId;
			this.selfDestructTime = selfDestructTime;
			this.selfDestructIn = selfDestructIn;
			this.autoDeleteIn = autoDeleteIn;
			this.viaBotUserId = viaBotUserId;
			this.authorSignature = authorSignature;
			this.mediaAlbumId = mediaAlbumId;
			this.restrictionReason = restrictionReason;
			this.content = content;
			this.replyMarkup = replyMarkup;
		}

		/**
		 * Describes a message.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public Message(DataInput input) throws IOException {
			this.id = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case MessageSenderUser.CONSTRUCTOR: this.senderId = new MessageSenderUser(input); break;
					case MessageSenderChat.CONSTRUCTOR: this.senderId = new MessageSenderChat(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case MessageSendingStatePending.CONSTRUCTOR: this.sendingState = new MessageSendingStatePending(input); break;
					case MessageSendingStateFailed.CONSTRUCTOR: this.sendingState = new MessageSendingStateFailed(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case MessageSchedulingStateSendAtDate.CONSTRUCTOR: this.schedulingState = new MessageSchedulingStateSendAtDate(input); break;
					case MessageSchedulingStateSendWhenOnline.CONSTRUCTOR: this.schedulingState = new MessageSchedulingStateSendWhenOnline(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.isOutgoing = input.readBoolean();
			this.isPinned = input.readBoolean();
			this.canBeEdited = input.readBoolean();
			this.canBeForwarded = input.readBoolean();
			this.canBeSaved = input.readBoolean();
			this.canBeDeletedOnlyForSelf = input.readBoolean();
			this.canBeDeletedForAllUsers = input.readBoolean();
			this.canGetAddedReactions = input.readBoolean();
			this.canGetStatistics = input.readBoolean();
			this.canGetMessageThread = input.readBoolean();
			this.canGetViewers = input.readBoolean();
			this.canGetMediaTimestampLinks = input.readBoolean();
			this.canReportReactions = input.readBoolean();
			this.hasTimestampedMedia = input.readBoolean();
			this.isChannelPost = input.readBoolean();
			this.isTopicMessage = input.readBoolean();
			this.containsUnreadMention = input.readBoolean();
			this.date = input.readInt();
			this.editDate = input.readInt();
			if (input.readBoolean()) {
				if (MessageForwardInfo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.forwardInfo = new MessageForwardInfo(input);
			}
			if (input.readBoolean()) {
				if (MessageInteractionInfo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.interactionInfo = new MessageInteractionInfo(input);
			}
			if (input.readBoolean()) {
				this.unreadReactions = new UnreadReaction[input.readInt()];
				for (int i = 0; i < this.unreadReactions.length; i++) {
					if (UnreadReaction.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.unreadReactions[i] = new UnreadReaction(input);
				}
			}
			this.replyInChatId = input.readLong();
			this.replyToMessageId = input.readLong();
			this.messageThreadId = input.readLong();
			this.selfDestructTime = input.readInt();
			this.selfDestructIn = input.readDouble();
			this.autoDeleteIn = input.readDouble();
			this.viaBotUserId = input.readLong();
			if (input.readBoolean()) {
				byte[] authorSignatureTmp = new byte[input.readInt()];
				input.readFully(authorSignatureTmp);
				this.authorSignature = new String(authorSignatureTmp, StandardCharsets.UTF_8);
			}
			this.mediaAlbumId = input.readLong();
			if (input.readBoolean()) {
				byte[] restrictionReasonTmp = new byte[input.readInt()];
				input.readFully(restrictionReasonTmp);
				this.restrictionReason = new String(restrictionReasonTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case MessageText.CONSTRUCTOR: this.content = new MessageText(input); break;
					case MessageAnimation.CONSTRUCTOR: this.content = new MessageAnimation(input); break;
					case MessageAudio.CONSTRUCTOR: this.content = new MessageAudio(input); break;
					case MessageDocument.CONSTRUCTOR: this.content = new MessageDocument(input); break;
					case MessagePhoto.CONSTRUCTOR: this.content = new MessagePhoto(input); break;
					case MessageExpiredPhoto.CONSTRUCTOR: this.content = new MessageExpiredPhoto(input); break;
					case MessageSticker.CONSTRUCTOR: this.content = new MessageSticker(input); break;
					case MessageVideo.CONSTRUCTOR: this.content = new MessageVideo(input); break;
					case MessageExpiredVideo.CONSTRUCTOR: this.content = new MessageExpiredVideo(input); break;
					case MessageVideoNote.CONSTRUCTOR: this.content = new MessageVideoNote(input); break;
					case MessageVoiceNote.CONSTRUCTOR: this.content = new MessageVoiceNote(input); break;
					case MessageLocation.CONSTRUCTOR: this.content = new MessageLocation(input); break;
					case MessageVenue.CONSTRUCTOR: this.content = new MessageVenue(input); break;
					case MessageContact.CONSTRUCTOR: this.content = new MessageContact(input); break;
					case MessageAnimatedEmoji.CONSTRUCTOR: this.content = new MessageAnimatedEmoji(input); break;
					case MessageDice.CONSTRUCTOR: this.content = new MessageDice(input); break;
					case MessageGame.CONSTRUCTOR: this.content = new MessageGame(input); break;
					case MessagePoll.CONSTRUCTOR: this.content = new MessagePoll(input); break;
					case MessageInvoice.CONSTRUCTOR: this.content = new MessageInvoice(input); break;
					case MessageCall.CONSTRUCTOR: this.content = new MessageCall(input); break;
					case MessageVideoChatScheduled.CONSTRUCTOR: this.content = new MessageVideoChatScheduled(input); break;
					case MessageVideoChatStarted.CONSTRUCTOR: this.content = new MessageVideoChatStarted(input); break;
					case MessageVideoChatEnded.CONSTRUCTOR: this.content = new MessageVideoChatEnded(input); break;
					case MessageInviteVideoChatParticipants.CONSTRUCTOR: this.content = new MessageInviteVideoChatParticipants(input); break;
					case MessageBasicGroupChatCreate.CONSTRUCTOR: this.content = new MessageBasicGroupChatCreate(input); break;
					case MessageSupergroupChatCreate.CONSTRUCTOR: this.content = new MessageSupergroupChatCreate(input); break;
					case MessageChatChangeTitle.CONSTRUCTOR: this.content = new MessageChatChangeTitle(input); break;
					case MessageChatChangePhoto.CONSTRUCTOR: this.content = new MessageChatChangePhoto(input); break;
					case MessageChatDeletePhoto.CONSTRUCTOR: this.content = new MessageChatDeletePhoto(input); break;
					case MessageChatAddMembers.CONSTRUCTOR: this.content = new MessageChatAddMembers(input); break;
					case MessageChatJoinByLink.CONSTRUCTOR: this.content = new MessageChatJoinByLink(input); break;
					case MessageChatJoinByRequest.CONSTRUCTOR: this.content = new MessageChatJoinByRequest(input); break;
					case MessageChatDeleteMember.CONSTRUCTOR: this.content = new MessageChatDeleteMember(input); break;
					case MessageChatUpgradeTo.CONSTRUCTOR: this.content = new MessageChatUpgradeTo(input); break;
					case MessageChatUpgradeFrom.CONSTRUCTOR: this.content = new MessageChatUpgradeFrom(input); break;
					case MessagePinMessage.CONSTRUCTOR: this.content = new MessagePinMessage(input); break;
					case MessageScreenshotTaken.CONSTRUCTOR: this.content = new MessageScreenshotTaken(input); break;
					case MessageChatSetBackground.CONSTRUCTOR: this.content = new MessageChatSetBackground(input); break;
					case MessageChatSetTheme.CONSTRUCTOR: this.content = new MessageChatSetTheme(input); break;
					case MessageChatSetMessageAutoDeleteTime.CONSTRUCTOR: this.content = new MessageChatSetMessageAutoDeleteTime(input); break;
					case MessageForumTopicCreated.CONSTRUCTOR: this.content = new MessageForumTopicCreated(input); break;
					case MessageForumTopicEdited.CONSTRUCTOR: this.content = new MessageForumTopicEdited(input); break;
					case MessageForumTopicIsClosedToggled.CONSTRUCTOR: this.content = new MessageForumTopicIsClosedToggled(input); break;
					case MessageForumTopicIsHiddenToggled.CONSTRUCTOR: this.content = new MessageForumTopicIsHiddenToggled(input); break;
					case MessageSuggestProfilePhoto.CONSTRUCTOR: this.content = new MessageSuggestProfilePhoto(input); break;
					case MessageCustomServiceAction.CONSTRUCTOR: this.content = new MessageCustomServiceAction(input); break;
					case MessageGameScore.CONSTRUCTOR: this.content = new MessageGameScore(input); break;
					case MessagePaymentSuccessful.CONSTRUCTOR: this.content = new MessagePaymentSuccessful(input); break;
					case MessagePaymentSuccessfulBot.CONSTRUCTOR: this.content = new MessagePaymentSuccessfulBot(input); break;
					case MessageGiftedPremium.CONSTRUCTOR: this.content = new MessageGiftedPremium(input); break;
					case MessageContactRegistered.CONSTRUCTOR: this.content = new MessageContactRegistered(input); break;
					case MessageUserShared.CONSTRUCTOR: this.content = new MessageUserShared(input); break;
					case MessageChatShared.CONSTRUCTOR: this.content = new MessageChatShared(input); break;
					case MessageWebsiteConnected.CONSTRUCTOR: this.content = new MessageWebsiteConnected(input); break;
					case MessageBotWriteAccessAllowed.CONSTRUCTOR: this.content = new MessageBotWriteAccessAllowed(input); break;
					case MessageWebAppDataSent.CONSTRUCTOR: this.content = new MessageWebAppDataSent(input); break;
					case MessageWebAppDataReceived.CONSTRUCTOR: this.content = new MessageWebAppDataReceived(input); break;
					case MessagePassportDataSent.CONSTRUCTOR: this.content = new MessagePassportDataSent(input); break;
					case MessagePassportDataReceived.CONSTRUCTOR: this.content = new MessagePassportDataReceived(input); break;
					case MessageProximityAlertTriggered.CONSTRUCTOR: this.content = new MessageProximityAlertTriggered(input); break;
					case MessageUnsupported.CONSTRUCTOR: this.content = new MessageUnsupported(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ReplyMarkupRemoveKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupRemoveKeyboard(input); break;
					case ReplyMarkupForceReply.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupForceReply(input); break;
					case ReplyMarkupShowKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupShowKeyboard(input); break;
					case ReplyMarkupInlineKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupInlineKeyboard(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return Message.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(Message.CONSTRUCTOR);
			output.writeLong(this.id);
			if (this.senderId == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.senderId.serialize(output);
			}
			output.writeLong(this.chatId);
			if (this.sendingState == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.sendingState.serialize(output);
			}
			if (this.schedulingState == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.schedulingState.serialize(output);
			}
			output.writeBoolean(this.isOutgoing);
			output.writeBoolean(this.isPinned);
			output.writeBoolean(this.canBeEdited);
			output.writeBoolean(this.canBeForwarded);
			output.writeBoolean(this.canBeSaved);
			output.writeBoolean(this.canBeDeletedOnlyForSelf);
			output.writeBoolean(this.canBeDeletedForAllUsers);
			output.writeBoolean(this.canGetAddedReactions);
			output.writeBoolean(this.canGetStatistics);
			output.writeBoolean(this.canGetMessageThread);
			output.writeBoolean(this.canGetViewers);
			output.writeBoolean(this.canGetMediaTimestampLinks);
			output.writeBoolean(this.canReportReactions);
			output.writeBoolean(this.hasTimestampedMedia);
			output.writeBoolean(this.isChannelPost);
			output.writeBoolean(this.isTopicMessage);
			output.writeBoolean(this.containsUnreadMention);
			output.writeInt(this.date);
			output.writeInt(this.editDate);
			if (this.forwardInfo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.forwardInfo.serialize(output);
			}
			if (this.interactionInfo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.interactionInfo.serialize(output);
			}
			if (this.unreadReactions == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.unreadReactions.length);
				for (int i = 0; i < this.unreadReactions.length; i++) {
					this.unreadReactions[i].serialize(output);
				}
			}
			output.writeLong(this.replyInChatId);
			output.writeLong(this.replyToMessageId);
			output.writeLong(this.messageThreadId);
			output.writeInt(this.selfDestructTime);
			output.writeDouble(this.selfDestructIn);
			output.writeDouble(this.autoDeleteIn);
			output.writeLong(this.viaBotUserId);
			if (this.authorSignature == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] authorSignatureTmp = this.authorSignature.getBytes(StandardCharsets.UTF_8);
				output.writeInt(authorSignatureTmp.length);
				output.write(authorSignatureTmp);
			}
			output.writeLong(this.mediaAlbumId);
			if (this.restrictionReason == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] restrictionReasonTmp = this.restrictionReason.getBytes(StandardCharsets.UTF_8);
				output.writeInt(restrictionReasonTmp.length);
				output.write(restrictionReasonTmp);
			}
			if (this.content == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.content.serialize(output);
			}
			if (this.replyMarkup == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.replyMarkup.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			Message message = (Message) o;
			if (this.id != message.id) {
				return false;
			}
			if (!Objects.equals(this.senderId, message.senderId)) {
				return false;
			}
			if (this.chatId != message.chatId) {
				return false;
			}
			if (!Objects.equals(this.sendingState, message.sendingState)) {
				return false;
			}
			if (!Objects.equals(this.schedulingState, message.schedulingState)) {
				return false;
			}
			if (this.isOutgoing != message.isOutgoing) {
				return false;
			}
			if (this.isPinned != message.isPinned) {
				return false;
			}
			if (this.canBeEdited != message.canBeEdited) {
				return false;
			}
			if (this.canBeForwarded != message.canBeForwarded) {
				return false;
			}
			if (this.canBeSaved != message.canBeSaved) {
				return false;
			}
			if (this.canBeDeletedOnlyForSelf != message.canBeDeletedOnlyForSelf) {
				return false;
			}
			if (this.canBeDeletedForAllUsers != message.canBeDeletedForAllUsers) {
				return false;
			}
			if (this.canGetAddedReactions != message.canGetAddedReactions) {
				return false;
			}
			if (this.canGetStatistics != message.canGetStatistics) {
				return false;
			}
			if (this.canGetMessageThread != message.canGetMessageThread) {
				return false;
			}
			if (this.canGetViewers != message.canGetViewers) {
				return false;
			}
			if (this.canGetMediaTimestampLinks != message.canGetMediaTimestampLinks) {
				return false;
			}
			if (this.canReportReactions != message.canReportReactions) {
				return false;
			}
			if (this.hasTimestampedMedia != message.hasTimestampedMedia) {
				return false;
			}
			if (this.isChannelPost != message.isChannelPost) {
				return false;
			}
			if (this.isTopicMessage != message.isTopicMessage) {
				return false;
			}
			if (this.containsUnreadMention != message.containsUnreadMention) {
				return false;
			}
			if (this.date != message.date) {
				return false;
			}
			if (this.editDate != message.editDate) {
				return false;
			}
			if (!Objects.equals(this.forwardInfo, message.forwardInfo)) {
				return false;
			}
			if (!Objects.equals(this.interactionInfo, message.interactionInfo)) {
				return false;
			}
			if (!Arrays.equals(this.unreadReactions, message.unreadReactions)) {
				return false;
			}
			if (this.replyInChatId != message.replyInChatId) {
				return false;
			}
			if (this.replyToMessageId != message.replyToMessageId) {
				return false;
			}
			if (this.messageThreadId != message.messageThreadId) {
				return false;
			}
			if (this.selfDestructTime != message.selfDestructTime) {
				return false;
			}
			if (this.selfDestructIn != message.selfDestructIn) {
				return false;
			}
			if (this.autoDeleteIn != message.autoDeleteIn) {
				return false;
			}
			if (this.viaBotUserId != message.viaBotUserId) {
				return false;
			}
			if (this.authorSignature != message.authorSignature) {
				return false;
			}
			if (this.mediaAlbumId != message.mediaAlbumId) {
				return false;
			}
			if (this.restrictionReason != message.restrictionReason) {
				return false;
			}
			if (!Objects.equals(this.content, message.content)) {
				return false;
			}
			if (!Objects.equals(this.replyMarkup, message.replyMarkup)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.id);
			result = result * 31 + (this.senderId == null ? 0 : this.senderId.hashCode());
			result = result * 31 + (this.sendingState == null ? 0 : this.sendingState.hashCode());
			result = result * 31 + (this.schedulingState == null ? 0 : this.schedulingState.hashCode());
			result = result * 31 + (this.forwardInfo == null ? 0 : this.forwardInfo.hashCode());
			result = result * 31 + (this.interactionInfo == null ? 0 : this.interactionInfo.hashCode());
			result = result * 31 + (Arrays.hashCode(this.unreadReactions));
			result = result * 31 + (this.authorSignature == null ? 0 : this.authorSignature.hashCode());
			result = result * 31 + (this.restrictionReason == null ? 0 : this.restrictionReason.hashCode());
			result = result * 31 + (this.content == null ? 0 : this.content.hashCode());
			result = result * 31 + (this.replyMarkup == null ? 0 : this.replyMarkup.hashCode());
			return result;
		}
	}

	/**
	 * Contains default auto-delete timer setting for new chats.
	**/
	public static final class MessageAutoDeleteTime extends Object {


		/**
		 * Message auto-delete time, in seconds. If 0, then messages aren&#039;t deleted automatically.
		**/
		public int time;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1972045589;

		/**
		 * Contains default auto-delete timer setting for new chats.
		**/
		public MessageAutoDeleteTime() {}

		/**
		 * Contains default auto-delete timer setting for new chats.
		 *
		 * @param time Message auto-delete time, in seconds. If 0, then messages aren&#039;t deleted automatically.
		**/
		public MessageAutoDeleteTime(int time) {
			this.time = time;
		}

		/**
		 * Contains default auto-delete timer setting for new chats.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageAutoDeleteTime(DataInput input) throws IOException {
			this.time = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageAutoDeleteTime.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageAutoDeleteTime.CONSTRUCTOR);
			output.writeInt(this.time);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageAutoDeleteTime messageAutoDeleteTime = (MessageAutoDeleteTime) o;
			if (this.time != messageAutoDeleteTime.time) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.time);
		}
	}

	/**
	 * Contains information about found messages, split by days according to
	 * the option &quot;utc_time_offset&quot;.
	**/
	public static final class MessageCalendar extends Object {


		/**
		 * Total number of found messages.
		**/
		public int totalCount;

		/**
		 * Information about messages sent.
		**/
		public MessageCalendarDay[] days;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1682890519;

		/**
		 * Contains information about found messages, split by days according to the option &quot;utc_time_offset&quot;.
		**/
		public MessageCalendar() {}

		/**
		 * Contains information about found messages, split by days according to the option &quot;utc_time_offset&quot;.
		 *
		 * @param totalCount Total number of found messages.
		 * @param days Information about messages sent.
		**/
		public MessageCalendar(int totalCount, MessageCalendarDay[] days) {
			this.totalCount = totalCount;
			this.days = days;
		}

		/**
		 * Contains information about found messages, split by days according to the option &quot;utc_time_offset&quot;.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageCalendar(DataInput input) throws IOException {
			this.totalCount = input.readInt();
			if (input.readBoolean()) {
				this.days = new MessageCalendarDay[input.readInt()];
				for (int i = 0; i < this.days.length; i++) {
					if (MessageCalendarDay.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.days[i] = new MessageCalendarDay(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageCalendar.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageCalendar.CONSTRUCTOR);
			output.writeInt(this.totalCount);
			if (this.days == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.days.length);
				for (int i = 0; i < this.days.length; i++) {
					this.days[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageCalendar messageCalendar = (MessageCalendar) o;
			if (this.totalCount != messageCalendar.totalCount) {
				return false;
			}
			if (!Arrays.equals(this.days, messageCalendar.days)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.totalCount);
			result = result * 31 + (Arrays.hashCode(this.days));
			return result;
		}
	}

	/**
	 * Contains information about found messages sent on a specific day.
	**/
	public static final class MessageCalendarDay extends Object {


		/**
		 * Total number of found messages sent on the day.
		**/
		public int totalCount;

		/**
		 * First message sent on the day.
		**/
		public Message message;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -376467614;

		/**
		 * Contains information about found messages sent on a specific day.
		**/
		public MessageCalendarDay() {}

		/**
		 * Contains information about found messages sent on a specific day.
		 *
		 * @param totalCount Total number of found messages sent on the day.
		 * @param message First message sent on the day.
		**/
		public MessageCalendarDay(int totalCount, Message message) {
			this.totalCount = totalCount;
			this.message = message;
		}

		/**
		 * Contains information about found messages sent on a specific day.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageCalendarDay(DataInput input) throws IOException {
			this.totalCount = input.readInt();
			if (input.readBoolean()) {
				if (Message.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.message = new Message(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageCalendarDay.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageCalendarDay.CONSTRUCTOR);
			output.writeInt(this.totalCount);
			if (this.message == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.message.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageCalendarDay messageCalendarDay = (MessageCalendarDay) o;
			if (this.totalCount != messageCalendarDay.totalCount) {
				return false;
			}
			if (!Objects.equals(this.message, messageCalendarDay.message)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.totalCount);
			result = result * 31 + (this.message == null ? 0 : this.message.hashCode());
			return result;
		}
	}

	/**
	 * A text message.
	**/
	public static final class MessageText extends MessageContent {


		/**
		 * Text of the message.
		**/
		public FormattedText text;

		/**
		 * A preview of the web page that&#039;s mentioned in the text; may be null.
		**/
		public WebPage webPage;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1989037971;

		/**
		 * A text message.
		**/
		public MessageText() {}

		/**
		 * A text message.
		 *
		 * @param text Text of the message.
		 * @param webPage A preview of the web page that&#039;s mentioned in the text; may be null.
		**/
		public MessageText(FormattedText text, WebPage webPage) {
			this.text = text;
			this.webPage = webPage;
		}

		/**
		 * A text message.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageText(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (FormattedText.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.text = new FormattedText(input);
			}
			if (input.readBoolean()) {
				if (WebPage.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.webPage = new WebPage(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageText.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageText.CONSTRUCTOR);
			if (this.text == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.text.serialize(output);
			}
			if (this.webPage == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.webPage.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageText messageText = (MessageText) o;
			if (!Objects.equals(this.text, messageText.text)) {
				return false;
			}
			if (!Objects.equals(this.webPage, messageText.webPage)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.text == null ? 0 : this.text.hashCode();
			result = result * 31 + (this.webPage == null ? 0 : this.webPage.hashCode());
			return result;
		}
	}

	/**
	 * An animation message (GIF-style).
	**/
	public static final class MessageAnimation extends MessageContent {


		/**
		 * The animation description.
		**/
		public Animation animation;

		/**
		 * Animation caption.
		**/
		public FormattedText caption;

		/**
		 * True, if the animation preview must be covered by a spoiler animation.
		**/
		public boolean hasSpoiler;

		/**
		 * True, if the animation thumbnail must be blurred and the animation must be shown only while tapped.
		**/
		public boolean isSecret;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1051944700;

		/**
		 * An animation message (GIF-style).
		**/
		public MessageAnimation() {}

		/**
		 * An animation message (GIF-style).
		 *
		 * @param animation The animation description.
		 * @param caption Animation caption.
		 * @param hasSpoiler True, if the animation preview must be covered by a spoiler animation.
		 * @param isSecret True, if the animation thumbnail must be blurred and the animation must be shown only while tapped.
		**/
		public MessageAnimation(Animation animation,
				FormattedText caption,
				boolean hasSpoiler,
				boolean isSecret) {
			this.animation = animation;
			this.caption = caption;
			this.hasSpoiler = hasSpoiler;
			this.isSecret = isSecret;
		}

		/**
		 * An animation message (GIF-style).
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageAnimation(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Animation.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.animation = new Animation(input);
			}
			if (input.readBoolean()) {
				if (FormattedText.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.caption = new FormattedText(input);
			}
			this.hasSpoiler = input.readBoolean();
			this.isSecret = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageAnimation.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageAnimation.CONSTRUCTOR);
			if (this.animation == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.animation.serialize(output);
			}
			if (this.caption == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.caption.serialize(output);
			}
			output.writeBoolean(this.hasSpoiler);
			output.writeBoolean(this.isSecret);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageAnimation messageAnimation = (MessageAnimation) o;
			if (!Objects.equals(this.animation, messageAnimation.animation)) {
				return false;
			}
			if (!Objects.equals(this.caption, messageAnimation.caption)) {
				return false;
			}
			if (this.hasSpoiler != messageAnimation.hasSpoiler) {
				return false;
			}
			if (this.isSecret != messageAnimation.isSecret) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.hasSpoiler);
			result = result * 31 + (this.animation == null ? 0 : this.animation.hashCode());
			result = result * 31 + (this.caption == null ? 0 : this.caption.hashCode());
			return result;
		}
	}

	/**
	 * An audio message.
	**/
	public static final class MessageAudio extends MessageContent {


		/**
		 * The audio description.
		**/
		public Audio audio;

		/**
		 * Audio caption.
		**/
		public FormattedText caption;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 276722716;

		/**
		 * An audio message.
		**/
		public MessageAudio() {}

		/**
		 * An audio message.
		 *
		 * @param audio The audio description.
		 * @param caption Audio caption.
		**/
		public MessageAudio(Audio audio, FormattedText caption) {
			this.audio = audio;
			this.caption = caption;
		}

		/**
		 * An audio message.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageAudio(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Audio.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.audio = new Audio(input);
			}
			if (input.readBoolean()) {
				if (FormattedText.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.caption = new FormattedText(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageAudio.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageAudio.CONSTRUCTOR);
			if (this.audio == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.audio.serialize(output);
			}
			if (this.caption == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.caption.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageAudio messageAudio = (MessageAudio) o;
			if (!Objects.equals(this.audio, messageAudio.audio)) {
				return false;
			}
			if (!Objects.equals(this.caption, messageAudio.caption)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.audio == null ? 0 : this.audio.hashCode();
			result = result * 31 + (this.caption == null ? 0 : this.caption.hashCode());
			return result;
		}
	}

	/**
	 * A document message (general file).
	**/
	public static final class MessageDocument extends MessageContent {


		/**
		 * The document description.
		**/
		public Document document;

		/**
		 * Document caption.
		**/
		public FormattedText caption;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 596945783;

		/**
		 * A document message (general file).
		**/
		public MessageDocument() {}

		/**
		 * A document message (general file).
		 *
		 * @param document The document description.
		 * @param caption Document caption.
		**/
		public MessageDocument(Document document, FormattedText caption) {
			this.document = document;
			this.caption = caption;
		}

		/**
		 * A document message (general file).
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageDocument(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Document.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.document = new Document(input);
			}
			if (input.readBoolean()) {
				if (FormattedText.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.caption = new FormattedText(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageDocument.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageDocument.CONSTRUCTOR);
			if (this.document == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.document.serialize(output);
			}
			if (this.caption == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.caption.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageDocument messageDocument = (MessageDocument) o;
			if (!Objects.equals(this.document, messageDocument.document)) {
				return false;
			}
			if (!Objects.equals(this.caption, messageDocument.caption)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.document == null ? 0 : this.document.hashCode();
			result = result * 31 + (this.caption == null ? 0 : this.caption.hashCode());
			return result;
		}
	}

	/**
	 * A photo message.
	**/
	public static final class MessagePhoto extends MessageContent {


		/**
		 * The photo.
		**/
		public Photo photo;

		/**
		 * Photo caption.
		**/
		public FormattedText caption;

		/**
		 * True, if the photo preview must be covered by a spoiler animation.
		**/
		public boolean hasSpoiler;

		/**
		 * True, if the photo must be blurred and must be shown only while tapped.
		**/
		public boolean isSecret;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -448050478;

		/**
		 * A photo message.
		**/
		public MessagePhoto() {}

		/**
		 * A photo message.
		 *
		 * @param photo The photo.
		 * @param caption Photo caption.
		 * @param hasSpoiler True, if the photo preview must be covered by a spoiler animation.
		 * @param isSecret True, if the photo must be blurred and must be shown only while tapped.
		**/
		public MessagePhoto(Photo photo,
				FormattedText caption,
				boolean hasSpoiler,
				boolean isSecret) {
			this.photo = photo;
			this.caption = caption;
			this.hasSpoiler = hasSpoiler;
			this.isSecret = isSecret;
		}

		/**
		 * A photo message.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessagePhoto(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Photo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.photo = new Photo(input);
			}
			if (input.readBoolean()) {
				if (FormattedText.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.caption = new FormattedText(input);
			}
			this.hasSpoiler = input.readBoolean();
			this.isSecret = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessagePhoto.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessagePhoto.CONSTRUCTOR);
			if (this.photo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.photo.serialize(output);
			}
			if (this.caption == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.caption.serialize(output);
			}
			output.writeBoolean(this.hasSpoiler);
			output.writeBoolean(this.isSecret);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessagePhoto messagePhoto = (MessagePhoto) o;
			if (!Objects.equals(this.photo, messagePhoto.photo)) {
				return false;
			}
			if (!Objects.equals(this.caption, messagePhoto.caption)) {
				return false;
			}
			if (this.hasSpoiler != messagePhoto.hasSpoiler) {
				return false;
			}
			if (this.isSecret != messagePhoto.isSecret) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.hasSpoiler);
			result = result * 31 + (this.photo == null ? 0 : this.photo.hashCode());
			result = result * 31 + (this.caption == null ? 0 : this.caption.hashCode());
			return result;
		}
	}

	/**
	 * A self-destructed photo message.
	**/
	public static final class MessageExpiredPhoto extends MessageContent {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1404641801;

		/**
		 * A self-destructed photo message.
		**/
		public MessageExpiredPhoto() {}

		/**
		 * A self-destructed photo message.
		 *
		**/

		/**
		 * A self-destructed photo message.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageExpiredPhoto(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageExpiredPhoto.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageExpiredPhoto.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return MessageExpiredPhoto.CONSTRUCTOR;
		}
	}

	/**
	 * A sticker message.
	**/
	public static final class MessageSticker extends MessageContent {


		/**
		 * The sticker description.
		**/
		public Sticker sticker;

		/**
		 * True, if premium animation of the sticker must be played.
		**/
		public boolean isPremium;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -437199670;

		/**
		 * A sticker message.
		**/
		public MessageSticker() {}

		/**
		 * A sticker message.
		 *
		 * @param sticker The sticker description.
		 * @param isPremium True, if premium animation of the sticker must be played.
		**/
		public MessageSticker(Sticker sticker, boolean isPremium) {
			this.sticker = sticker;
			this.isPremium = isPremium;
		}

		/**
		 * A sticker message.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageSticker(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Sticker.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.sticker = new Sticker(input);
			}
			this.isPremium = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageSticker.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageSticker.CONSTRUCTOR);
			if (this.sticker == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.sticker.serialize(output);
			}
			output.writeBoolean(this.isPremium);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageSticker messageSticker = (MessageSticker) o;
			if (!Objects.equals(this.sticker, messageSticker.sticker)) {
				return false;
			}
			if (this.isPremium != messageSticker.isPremium) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isPremium);
			result = result * 31 + (this.sticker == null ? 0 : this.sticker.hashCode());
			return result;
		}
	}

	/**
	 * A video message.
	**/
	public static final class MessageVideo extends MessageContent {


		/**
		 * The video description.
		**/
		public Video video;

		/**
		 * Video caption.
		**/
		public FormattedText caption;

		/**
		 * True, if the video preview must be covered by a spoiler animation.
		**/
		public boolean hasSpoiler;

		/**
		 * True, if the video thumbnail must be blurred and the video must be shown only while tapped.
		**/
		public boolean isSecret;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1237516229;

		/**
		 * A video message.
		**/
		public MessageVideo() {}

		/**
		 * A video message.
		 *
		 * @param video The video description.
		 * @param caption Video caption.
		 * @param hasSpoiler True, if the video preview must be covered by a spoiler animation.
		 * @param isSecret True, if the video thumbnail must be blurred and the video must be shown only while tapped.
		**/
		public MessageVideo(Video video,
				FormattedText caption,
				boolean hasSpoiler,
				boolean isSecret) {
			this.video = video;
			this.caption = caption;
			this.hasSpoiler = hasSpoiler;
			this.isSecret = isSecret;
		}

		/**
		 * A video message.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageVideo(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Video.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.video = new Video(input);
			}
			if (input.readBoolean()) {
				if (FormattedText.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.caption = new FormattedText(input);
			}
			this.hasSpoiler = input.readBoolean();
			this.isSecret = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageVideo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageVideo.CONSTRUCTOR);
			if (this.video == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.video.serialize(output);
			}
			if (this.caption == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.caption.serialize(output);
			}
			output.writeBoolean(this.hasSpoiler);
			output.writeBoolean(this.isSecret);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageVideo messageVideo = (MessageVideo) o;
			if (!Objects.equals(this.video, messageVideo.video)) {
				return false;
			}
			if (!Objects.equals(this.caption, messageVideo.caption)) {
				return false;
			}
			if (this.hasSpoiler != messageVideo.hasSpoiler) {
				return false;
			}
			if (this.isSecret != messageVideo.isSecret) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.hasSpoiler);
			result = result * 31 + (this.video == null ? 0 : this.video.hashCode());
			result = result * 31 + (this.caption == null ? 0 : this.caption.hashCode());
			return result;
		}
	}

	/**
	 * A self-destructed video message.
	**/
	public static final class MessageExpiredVideo extends MessageContent {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1212209981;

		/**
		 * A self-destructed video message.
		**/
		public MessageExpiredVideo() {}

		/**
		 * A self-destructed video message.
		 *
		**/

		/**
		 * A self-destructed video message.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageExpiredVideo(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageExpiredVideo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageExpiredVideo.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return MessageExpiredVideo.CONSTRUCTOR;
		}
	}

	/**
	 * A video note message.
	**/
	public static final class MessageVideoNote extends MessageContent {


		/**
		 * The video note description.
		**/
		public VideoNote videoNote;

		/**
		 * True, if at least one of the recipients has viewed the video note.
		**/
		public boolean isViewed;

		/**
		 * True, if the video note thumbnail must be blurred and the video note must be shown only while tapped.
		**/
		public boolean isSecret;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 963323014;

		/**
		 * A video note message.
		**/
		public MessageVideoNote() {}

		/**
		 * A video note message.
		 *
		 * @param videoNote The video note description.
		 * @param isViewed True, if at least one of the recipients has viewed the video note.
		 * @param isSecret True, if the video note thumbnail must be blurred and the video note must be shown only while tapped.
		**/
		public MessageVideoNote(VideoNote videoNote, boolean isViewed, boolean isSecret) {
			this.videoNote = videoNote;
			this.isViewed = isViewed;
			this.isSecret = isSecret;
		}

		/**
		 * A video note message.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageVideoNote(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (VideoNote.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.videoNote = new VideoNote(input);
			}
			this.isViewed = input.readBoolean();
			this.isSecret = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageVideoNote.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageVideoNote.CONSTRUCTOR);
			if (this.videoNote == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.videoNote.serialize(output);
			}
			output.writeBoolean(this.isViewed);
			output.writeBoolean(this.isSecret);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageVideoNote messageVideoNote = (MessageVideoNote) o;
			if (!Objects.equals(this.videoNote, messageVideoNote.videoNote)) {
				return false;
			}
			if (this.isViewed != messageVideoNote.isViewed) {
				return false;
			}
			if (this.isSecret != messageVideoNote.isSecret) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isViewed);
			result = result * 31 + (this.videoNote == null ? 0 : this.videoNote.hashCode());
			return result;
		}
	}

	/**
	 * A voice note message.
	**/
	public static final class MessageVoiceNote extends MessageContent {


		/**
		 * The voice note description.
		**/
		public VoiceNote voiceNote;

		/**
		 * Voice note caption.
		**/
		public FormattedText caption;

		/**
		 * True, if at least one of the recipients has listened to the voice note.
		**/
		public boolean isListened;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 527777781;

		/**
		 * A voice note message.
		**/
		public MessageVoiceNote() {}

		/**
		 * A voice note message.
		 *
		 * @param voiceNote The voice note description.
		 * @param caption Voice note caption.
		 * @param isListened True, if at least one of the recipients has listened to the voice note.
		**/
		public MessageVoiceNote(VoiceNote voiceNote,
				FormattedText caption,
				boolean isListened) {
			this.voiceNote = voiceNote;
			this.caption = caption;
			this.isListened = isListened;
		}

		/**
		 * A voice note message.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageVoiceNote(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (VoiceNote.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.voiceNote = new VoiceNote(input);
			}
			if (input.readBoolean()) {
				if (FormattedText.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.caption = new FormattedText(input);
			}
			this.isListened = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageVoiceNote.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageVoiceNote.CONSTRUCTOR);
			if (this.voiceNote == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.voiceNote.serialize(output);
			}
			if (this.caption == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.caption.serialize(output);
			}
			output.writeBoolean(this.isListened);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageVoiceNote messageVoiceNote = (MessageVoiceNote) o;
			if (!Objects.equals(this.voiceNote, messageVoiceNote.voiceNote)) {
				return false;
			}
			if (!Objects.equals(this.caption, messageVoiceNote.caption)) {
				return false;
			}
			if (this.isListened != messageVoiceNote.isListened) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isListened);
			result = result * 31 + (this.voiceNote == null ? 0 : this.voiceNote.hashCode());
			result = result * 31 + (this.caption == null ? 0 : this.caption.hashCode());
			return result;
		}
	}

	/**
	 * A message with a location.
	**/
	public static final class MessageLocation extends MessageContent {


		/**
		 * The location description.
		**/
		public Location location;

		/**
		 * Time relative to the message send date, for which the location can be updated, in seconds.
		**/
		public int livePeriod;

		/**
		 * Left time for which the location can be updated, in seconds. updateMessageContent is not sent when this field changes.
		**/
		public int expiresIn;

		/**
		 * For live locations, a direction in which the location moves, in degrees; 1-360. If 0 the direction is unknown.
		**/
		public int heading;

		/**
		 * For live locations, a maximum distance to another chat member for proximity alerts, in meters (0-100000). 0 if the notification is disabled. Available only to the message sender.
		**/
		public int proximityAlertRadius;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 303973492;

		/**
		 * A message with a location.
		**/
		public MessageLocation() {}

		/**
		 * A message with a location.
		 *
		 * @param location The location description.
		 * @param livePeriod Time relative to the message send date, for which the location can be updated, in seconds.
		 * @param expiresIn Left time for which the location can be updated, in seconds. updateMessageContent is not sent when this field changes.
		 * @param heading For live locations, a direction in which the location moves, in degrees; 1-360. If 0 the direction is unknown.
		 * @param proximityAlertRadius For live locations, a maximum distance to another chat member for proximity alerts, in meters (0-100000). 0 if the notification is disabled. Available only to the message sender.
		**/
		public MessageLocation(Location location,
				int livePeriod,
				int expiresIn,
				int heading,
				int proximityAlertRadius) {
			this.location = location;
			this.livePeriod = livePeriod;
			this.expiresIn = expiresIn;
			this.heading = heading;
			this.proximityAlertRadius = proximityAlertRadius;
		}

		/**
		 * A message with a location.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageLocation(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Location.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.location = new Location(input);
			}
			this.livePeriod = input.readInt();
			this.expiresIn = input.readInt();
			this.heading = input.readInt();
			this.proximityAlertRadius = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageLocation.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageLocation.CONSTRUCTOR);
			if (this.location == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.location.serialize(output);
			}
			output.writeInt(this.livePeriod);
			output.writeInt(this.expiresIn);
			output.writeInt(this.heading);
			output.writeInt(this.proximityAlertRadius);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageLocation messageLocation = (MessageLocation) o;
			if (!Objects.equals(this.location, messageLocation.location)) {
				return false;
			}
			if (this.livePeriod != messageLocation.livePeriod) {
				return false;
			}
			if (this.expiresIn != messageLocation.expiresIn) {
				return false;
			}
			if (this.heading != messageLocation.heading) {
				return false;
			}
			if (this.proximityAlertRadius != messageLocation.proximityAlertRadius) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.livePeriod);
			result = result * 31 + (this.location == null ? 0 : this.location.hashCode());
			return result;
		}
	}

	/**
	 * A message with information about a venue.
	**/
	public static final class MessageVenue extends MessageContent {


		/**
		 * The venue description.
		**/
		public Venue venue;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2146492043;

		/**
		 * A message with information about a venue.
		**/
		public MessageVenue() {}

		/**
		 * A message with information about a venue.
		 *
		 * @param venue The venue description.
		**/
		public MessageVenue(Venue venue) {
			this.venue = venue;
		}

		/**
		 * A message with information about a venue.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageVenue(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Venue.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.venue = new Venue(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageVenue.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageVenue.CONSTRUCTOR);
			if (this.venue == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.venue.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageVenue messageVenue = (MessageVenue) o;
			if (!Objects.equals(this.venue, messageVenue.venue)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.venue == null ? 0 : this.venue.hashCode();
		}
	}

	/**
	 * A message with a user contact.
	**/
	public static final class MessageContact extends MessageContent {


		/**
		 * The contact description.
		**/
		public Contact contact;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -512684966;

		/**
		 * A message with a user contact.
		**/
		public MessageContact() {}

		/**
		 * A message with a user contact.
		 *
		 * @param contact The contact description.
		**/
		public MessageContact(Contact contact) {
			this.contact = contact;
		}

		/**
		 * A message with a user contact.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageContact(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Contact.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.contact = new Contact(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageContact.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageContact.CONSTRUCTOR);
			if (this.contact == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.contact.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageContact messageContact = (MessageContact) o;
			if (!Objects.equals(this.contact, messageContact.contact)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.contact == null ? 0 : this.contact.hashCode();
		}
	}

	/**
	 * A message with an animated emoji.
	**/
	public static final class MessageAnimatedEmoji extends MessageContent {


		/**
		 * The animated emoji.
		**/
		public AnimatedEmoji animatedEmoji;

		/**
		 * The corresponding emoji.
		**/
		public String emoji;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 908195298;

		/**
		 * A message with an animated emoji.
		**/
		public MessageAnimatedEmoji() {}

		/**
		 * A message with an animated emoji.
		 *
		 * @param animatedEmoji The animated emoji.
		 * @param emoji The corresponding emoji.
		**/
		public MessageAnimatedEmoji(AnimatedEmoji animatedEmoji, String emoji) {
			this.animatedEmoji = animatedEmoji;
			this.emoji = emoji;
		}

		/**
		 * A message with an animated emoji.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageAnimatedEmoji(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (AnimatedEmoji.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.animatedEmoji = new AnimatedEmoji(input);
			}
			if (input.readBoolean()) {
				byte[] emojiTmp = new byte[input.readInt()];
				input.readFully(emojiTmp);
				this.emoji = new String(emojiTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageAnimatedEmoji.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageAnimatedEmoji.CONSTRUCTOR);
			if (this.animatedEmoji == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.animatedEmoji.serialize(output);
			}
			if (this.emoji == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] emojiTmp = this.emoji.getBytes(StandardCharsets.UTF_8);
				output.writeInt(emojiTmp.length);
				output.write(emojiTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageAnimatedEmoji messageAnimatedEmoji = (MessageAnimatedEmoji) o;
			if (!Objects.equals(this.animatedEmoji, messageAnimatedEmoji.animatedEmoji)) {
				return false;
			}
			if (this.emoji != messageAnimatedEmoji.emoji) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.animatedEmoji == null ? 0 : this.animatedEmoji.hashCode();
			result = result * 31 + (this.emoji == null ? 0 : this.emoji.hashCode());
			return result;
		}
	}

	/**
	 * A dice message. The dice value is randomly generated by the server.
	**/
	public static final class MessageDice extends MessageContent {


		/**
		 * The animated stickers with the initial dice animation; may be null if unknown. updateMessageContent will be sent when the sticker became known.
		**/
		public DiceStickers initialState;

		/**
		 * The animated stickers with the final dice animation; may be null if unknown. updateMessageContent will be sent when the sticker became known.
		**/
		public DiceStickers finalState;

		/**
		 * Emoji on which the dice throw animation is based.
		**/
		public String emoji;

		/**
		 * The dice value. If the value is 0, the dice don&#039;t have final state yet.
		**/
		public int value;

		/**
		 * Number of frame after which a success animation like a shower of confetti needs to be shown on updateMessageSendSucceeded.
		**/
		public int successAnimationFrameNumber;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1115779641;

		/**
		 * A dice message. The dice value is randomly generated by the server.
		**/
		public MessageDice() {}

		/**
		 * A dice message. The dice value is randomly generated by the server.
		 *
		 * @param initialState The animated stickers with the initial dice animation; may be null if unknown. updateMessageContent will be sent when the sticker became known.
		 * @param finalState The animated stickers with the final dice animation; may be null if unknown. updateMessageContent will be sent when the sticker became known.
		 * @param emoji Emoji on which the dice throw animation is based.
		 * @param value The dice value. If the value is 0, the dice don&#039;t have final state yet.
		 * @param successAnimationFrameNumber Number of frame after which a success animation like a shower of confetti needs to be shown on updateMessageSendSucceeded.
		**/
		public MessageDice(DiceStickers initialState,
				DiceStickers finalState,
				String emoji,
				int value,
				int successAnimationFrameNumber) {
			this.initialState = initialState;
			this.finalState = finalState;
			this.emoji = emoji;
			this.value = value;
			this.successAnimationFrameNumber = successAnimationFrameNumber;
		}

		/**
		 * A dice message. The dice value is randomly generated by the server.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageDice(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case DiceStickersRegular.CONSTRUCTOR: this.initialState = new DiceStickersRegular(input); break;
					case DiceStickersSlotMachine.CONSTRUCTOR: this.initialState = new DiceStickersSlotMachine(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case DiceStickersRegular.CONSTRUCTOR: this.finalState = new DiceStickersRegular(input); break;
					case DiceStickersSlotMachine.CONSTRUCTOR: this.finalState = new DiceStickersSlotMachine(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				byte[] emojiTmp = new byte[input.readInt()];
				input.readFully(emojiTmp);
				this.emoji = new String(emojiTmp, StandardCharsets.UTF_8);
			}
			this.value = input.readInt();
			this.successAnimationFrameNumber = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageDice.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageDice.CONSTRUCTOR);
			if (this.initialState == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.initialState.serialize(output);
			}
			if (this.finalState == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.finalState.serialize(output);
			}
			if (this.emoji == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] emojiTmp = this.emoji.getBytes(StandardCharsets.UTF_8);
				output.writeInt(emojiTmp.length);
				output.write(emojiTmp);
			}
			output.writeInt(this.value);
			output.writeInt(this.successAnimationFrameNumber);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageDice messageDice = (MessageDice) o;
			if (!Objects.equals(this.initialState, messageDice.initialState)) {
				return false;
			}
			if (!Objects.equals(this.finalState, messageDice.finalState)) {
				return false;
			}
			if (this.emoji != messageDice.emoji) {
				return false;
			}
			if (this.value != messageDice.value) {
				return false;
			}
			if (this.successAnimationFrameNumber != messageDice.successAnimationFrameNumber) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.value);
			result = result * 31 + (this.initialState == null ? 0 : this.initialState.hashCode());
			result = result * 31 + (this.finalState == null ? 0 : this.finalState.hashCode());
			result = result * 31 + (this.emoji == null ? 0 : this.emoji.hashCode());
			return result;
		}
	}

	/**
	 * A message with a game.
	**/
	public static final class MessageGame extends MessageContent {


		/**
		 * The game description.
		**/
		public Game game;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -69441162;

		/**
		 * A message with a game.
		**/
		public MessageGame() {}

		/**
		 * A message with a game.
		 *
		 * @param game The game description.
		**/
		public MessageGame(Game game) {
			this.game = game;
		}

		/**
		 * A message with a game.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageGame(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Game.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.game = new Game(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageGame.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageGame.CONSTRUCTOR);
			if (this.game == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.game.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageGame messageGame = (MessageGame) o;
			if (!Objects.equals(this.game, messageGame.game)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.game == null ? 0 : this.game.hashCode();
		}
	}

	/**
	 * A message with a poll.
	**/
	public static final class MessagePoll extends MessageContent {


		/**
		 * The poll description.
		**/
		public Poll poll;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -662130099;

		/**
		 * A message with a poll.
		**/
		public MessagePoll() {}

		/**
		 * A message with a poll.
		 *
		 * @param poll The poll description.
		**/
		public MessagePoll(Poll poll) {
			this.poll = poll;
		}

		/**
		 * A message with a poll.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessagePoll(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Poll.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.poll = new Poll(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessagePoll.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessagePoll.CONSTRUCTOR);
			if (this.poll == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.poll.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessagePoll messagePoll = (MessagePoll) o;
			if (!Objects.equals(this.poll, messagePoll.poll)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.poll == null ? 0 : this.poll.hashCode();
		}
	}

	/**
	 * A message with an invoice from a bot. Use getInternalLink with
	 * internalLinkTypeBotStart to share the invoice.
	**/
	public static final class MessageInvoice extends MessageContent {


		/**
		 * Product title.
		**/
		public String title;

		/**
		 * Product description.
		**/
		public FormattedText description;

		/**
		 * Product photo; may be null.
		**/
		public Photo photo;

		/**
		 * Currency for the product price.
		**/
		public String currency;

		/**
		 * Product total price in the smallest units of the currency.
		**/
		public long totalAmount;

		/**
		 * Unique invoice bot startParameter to be passed to getInternalLink.
		**/
		public String startParameter;

		/**
		 * True, if the invoice is a test invoice.
		**/
		public boolean isTest;

		/**
		 * True, if the shipping address must be specified.
		**/
		public boolean needShippingAddress;

		/**
		 * The identifier of the message with the receipt, after the product has been purchased.
		**/
		public long receiptMessageId;

		/**
		 * Extended media attached to the invoice; may be null.
		**/
		public MessageExtendedMedia extendedMedia;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 818077142;

		/**
		 * A message with an invoice from a bot. Use getInternalLink with internalLinkTypeBotStart to share the invoice.
		**/
		public MessageInvoice() {}

		/**
		 * A message with an invoice from a bot. Use getInternalLink with internalLinkTypeBotStart to share the invoice.
		 *
		 * @param title Product title.
		 * @param description Product description.
		 * @param photo Product photo; may be null.
		 * @param currency Currency for the product price.
		 * @param totalAmount Product total price in the smallest units of the currency.
		 * @param startParameter Unique invoice bot startParameter to be passed to getInternalLink.
		 * @param isTest True, if the invoice is a test invoice.
		 * @param needShippingAddress True, if the shipping address must be specified.
		 * @param receiptMessageId The identifier of the message with the receipt, after the product has been purchased.
		 * @param extendedMedia Extended media attached to the invoice; may be null.
		**/
		public MessageInvoice(String title,
				FormattedText description,
				Photo photo,
				String currency,
				long totalAmount,
				String startParameter,
				boolean isTest,
				boolean needShippingAddress,
				long receiptMessageId,
				MessageExtendedMedia extendedMedia) {
			this.title = title;
			this.description = description;
			this.photo = photo;
			this.currency = currency;
			this.totalAmount = totalAmount;
			this.startParameter = startParameter;
			this.isTest = isTest;
			this.needShippingAddress = needShippingAddress;
			this.receiptMessageId = receiptMessageId;
			this.extendedMedia = extendedMedia;
		}

		/**
		 * A message with an invoice from a bot. Use getInternalLink with internalLinkTypeBotStart to share the invoice.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageInvoice(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (FormattedText.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.description = new FormattedText(input);
			}
			if (input.readBoolean()) {
				if (Photo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.photo = new Photo(input);
			}
			if (input.readBoolean()) {
				byte[] currencyTmp = new byte[input.readInt()];
				input.readFully(currencyTmp);
				this.currency = new String(currencyTmp, StandardCharsets.UTF_8);
			}
			this.totalAmount = input.readLong();
			if (input.readBoolean()) {
				byte[] startParameterTmp = new byte[input.readInt()];
				input.readFully(startParameterTmp);
				this.startParameter = new String(startParameterTmp, StandardCharsets.UTF_8);
			}
			this.isTest = input.readBoolean();
			this.needShippingAddress = input.readBoolean();
			this.receiptMessageId = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case MessageExtendedMediaPreview.CONSTRUCTOR: this.extendedMedia = new MessageExtendedMediaPreview(input); break;
					case MessageExtendedMediaPhoto.CONSTRUCTOR: this.extendedMedia = new MessageExtendedMediaPhoto(input); break;
					case MessageExtendedMediaVideo.CONSTRUCTOR: this.extendedMedia = new MessageExtendedMediaVideo(input); break;
					case MessageExtendedMediaUnsupported.CONSTRUCTOR: this.extendedMedia = new MessageExtendedMediaUnsupported(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageInvoice.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageInvoice.CONSTRUCTOR);
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
			if (this.description == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.description.serialize(output);
			}
			if (this.photo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.photo.serialize(output);
			}
			if (this.currency == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] currencyTmp = this.currency.getBytes(StandardCharsets.UTF_8);
				output.writeInt(currencyTmp.length);
				output.write(currencyTmp);
			}
			output.writeLong(this.totalAmount);
			if (this.startParameter == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] startParameterTmp = this.startParameter.getBytes(StandardCharsets.UTF_8);
				output.writeInt(startParameterTmp.length);
				output.write(startParameterTmp);
			}
			output.writeBoolean(this.isTest);
			output.writeBoolean(this.needShippingAddress);
			output.writeLong(this.receiptMessageId);
			if (this.extendedMedia == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.extendedMedia.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageInvoice messageInvoice = (MessageInvoice) o;
			if (this.title != messageInvoice.title) {
				return false;
			}
			if (!Objects.equals(this.description, messageInvoice.description)) {
				return false;
			}
			if (!Objects.equals(this.photo, messageInvoice.photo)) {
				return false;
			}
			if (this.currency != messageInvoice.currency) {
				return false;
			}
			if (this.totalAmount != messageInvoice.totalAmount) {
				return false;
			}
			if (this.startParameter != messageInvoice.startParameter) {
				return false;
			}
			if (this.isTest != messageInvoice.isTest) {
				return false;
			}
			if (this.needShippingAddress != messageInvoice.needShippingAddress) {
				return false;
			}
			if (this.receiptMessageId != messageInvoice.receiptMessageId) {
				return false;
			}
			if (!Objects.equals(this.extendedMedia, messageInvoice.extendedMedia)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.totalAmount);
			result = result * 31 + (this.title == null ? 0 : this.title.hashCode());
			result = result * 31 + (this.description == null ? 0 : this.description.hashCode());
			result = result * 31 + (this.photo == null ? 0 : this.photo.hashCode());
			result = result * 31 + (this.currency == null ? 0 : this.currency.hashCode());
			result = result * 31 + (this.startParameter == null ? 0 : this.startParameter.hashCode());
			result = result * 31 + (this.extendedMedia == null ? 0 : this.extendedMedia.hashCode());
			return result;
		}
	}

	/**
	 * A message with information about an ended call.
	**/
	public static final class MessageCall extends MessageContent {


		/**
		 * True, if the call was a video call.
		**/
		public boolean isVideo;

		/**
		 * Reason why the call was discarded.
		**/
		public CallDiscardReason discardReason;

		/**
		 * Call duration, in seconds.
		**/
		public int duration;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 538893824;

		/**
		 * A message with information about an ended call.
		**/
		public MessageCall() {}

		/**
		 * A message with information about an ended call.
		 *
		 * @param isVideo True, if the call was a video call.
		 * @param discardReason Reason why the call was discarded.
		 * @param duration Call duration, in seconds.
		**/
		public MessageCall(boolean isVideo,
				CallDiscardReason discardReason,
				int duration) {
			this.isVideo = isVideo;
			this.discardReason = discardReason;
			this.duration = duration;
		}

		/**
		 * A message with information about an ended call.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageCall(DataInput input) throws IOException {
			this.isVideo = input.readBoolean();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case CallDiscardReasonEmpty.CONSTRUCTOR: this.discardReason = new CallDiscardReasonEmpty(input); break;
					case CallDiscardReasonMissed.CONSTRUCTOR: this.discardReason = new CallDiscardReasonMissed(input); break;
					case CallDiscardReasonDeclined.CONSTRUCTOR: this.discardReason = new CallDiscardReasonDeclined(input); break;
					case CallDiscardReasonDisconnected.CONSTRUCTOR: this.discardReason = new CallDiscardReasonDisconnected(input); break;
					case CallDiscardReasonHungUp.CONSTRUCTOR: this.discardReason = new CallDiscardReasonHungUp(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.duration = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageCall.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageCall.CONSTRUCTOR);
			output.writeBoolean(this.isVideo);
			if (this.discardReason == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.discardReason.serialize(output);
			}
			output.writeInt(this.duration);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageCall messageCall = (MessageCall) o;
			if (this.isVideo != messageCall.isVideo) {
				return false;
			}
			if (!Objects.equals(this.discardReason, messageCall.discardReason)) {
				return false;
			}
			if (this.duration != messageCall.duration) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isVideo);
			result = result * 31 + (this.discardReason == null ? 0 : this.discardReason.hashCode());
			return result;
		}
	}

	/**
	 * A new video chat was scheduled.
	**/
	public static final class MessageVideoChatScheduled extends MessageContent {


		/**
		 * Identifier of the video chat. The video chat can be received through the method getGroupCall.
		**/
		public int groupCallId;

		/**
		 * Point in time (Unix timestamp) when the group call is supposed to be started by an administrator.
		**/
		public int startDate;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1855185481;

		/**
		 * A new video chat was scheduled.
		**/
		public MessageVideoChatScheduled() {}

		/**
		 * A new video chat was scheduled.
		 *
		 * @param groupCallId Identifier of the video chat. The video chat can be received through the method getGroupCall.
		 * @param startDate Point in time (Unix timestamp) when the group call is supposed to be started by an administrator.
		**/
		public MessageVideoChatScheduled(int groupCallId, int startDate) {
			this.groupCallId = groupCallId;
			this.startDate = startDate;
		}

		/**
		 * A new video chat was scheduled.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageVideoChatScheduled(DataInput input) throws IOException {
			this.groupCallId = input.readInt();
			this.startDate = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageVideoChatScheduled.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageVideoChatScheduled.CONSTRUCTOR);
			output.writeInt(this.groupCallId);
			output.writeInt(this.startDate);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageVideoChatScheduled messageVideoChatScheduled = (MessageVideoChatScheduled) o;
			if (this.groupCallId != messageVideoChatScheduled.groupCallId) {
				return false;
			}
			if (this.startDate != messageVideoChatScheduled.startDate) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.groupCallId);
			return result;
		}
	}

	/**
	 * A newly created video chat.
	**/
	public static final class MessageVideoChatStarted extends MessageContent {


		/**
		 * Identifier of the video chat. The video chat can be received through the method getGroupCall.
		**/
		public int groupCallId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 521225561;

		/**
		 * A newly created video chat.
		**/
		public MessageVideoChatStarted() {}

		/**
		 * A newly created video chat.
		 *
		 * @param groupCallId Identifier of the video chat. The video chat can be received through the method getGroupCall.
		**/
		public MessageVideoChatStarted(int groupCallId) {
			this.groupCallId = groupCallId;
		}

		/**
		 * A newly created video chat.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageVideoChatStarted(DataInput input) throws IOException {
			this.groupCallId = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageVideoChatStarted.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageVideoChatStarted.CONSTRUCTOR);
			output.writeInt(this.groupCallId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageVideoChatStarted messageVideoChatStarted = (MessageVideoChatStarted) o;
			if (this.groupCallId != messageVideoChatStarted.groupCallId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.groupCallId);
		}
	}

	/**
	 * A message with information about an ended video chat.
	**/
	public static final class MessageVideoChatEnded extends MessageContent {


		/**
		 * Call duration, in seconds.
		**/
		public int duration;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2032544855;

		/**
		 * A message with information about an ended video chat.
		**/
		public MessageVideoChatEnded() {}

		/**
		 * A message with information about an ended video chat.
		 *
		 * @param duration Call duration, in seconds.
		**/
		public MessageVideoChatEnded(int duration) {
			this.duration = duration;
		}

		/**
		 * A message with information about an ended video chat.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageVideoChatEnded(DataInput input) throws IOException {
			this.duration = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageVideoChatEnded.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageVideoChatEnded.CONSTRUCTOR);
			output.writeInt(this.duration);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageVideoChatEnded messageVideoChatEnded = (MessageVideoChatEnded) o;
			if (this.duration != messageVideoChatEnded.duration) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.duration);
		}
	}

	/**
	 * A message with information about an invite to a video chat.
	**/
	public static final class MessageInviteVideoChatParticipants extends MessageContent {


		/**
		 * Identifier of the video chat. The video chat can be received through the method getGroupCall.
		**/
		public int groupCallId;

		/**
		 * Invited user identifiers.
		**/
		public long[] userIds;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1459065585;

		/**
		 * A message with information about an invite to a video chat.
		**/
		public MessageInviteVideoChatParticipants() {}

		/**
		 * A message with information about an invite to a video chat.
		 *
		 * @param groupCallId Identifier of the video chat. The video chat can be received through the method getGroupCall.
		 * @param userIds Invited user identifiers.
		**/
		public MessageInviteVideoChatParticipants(int groupCallId, long[] userIds) {
			this.groupCallId = groupCallId;
			this.userIds = userIds;
		}

		/**
		 * A message with information about an invite to a video chat.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageInviteVideoChatParticipants(DataInput input) throws IOException {
			this.groupCallId = input.readInt();
			if (input.readBoolean()) {
				this.userIds = new long[input.readInt()];
				for (int i = 0; i < this.userIds.length; i++) {
					this.userIds[i] = input.readLong();
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageInviteVideoChatParticipants.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageInviteVideoChatParticipants.CONSTRUCTOR);
			output.writeInt(this.groupCallId);
			if (this.userIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.userIds.length);
				for (int i = 0; i < this.userIds.length; i++) {
					output.writeLong(this.userIds[i]);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageInviteVideoChatParticipants messageInviteVideoChatParticipants = (MessageInviteVideoChatParticipants) o;
			if (this.groupCallId != messageInviteVideoChatParticipants.groupCallId) {
				return false;
			}
			if (!Arrays.equals(this.userIds, messageInviteVideoChatParticipants.userIds)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.groupCallId);
			result = result * 31 + (Arrays.hashCode(this.userIds));
			return result;
		}
	}

	/**
	 * A newly created basic group.
	**/
	public static final class MessageBasicGroupChatCreate extends MessageContent {


		/**
		 * Title of the basic group.
		**/
		public String title;

		/**
		 * User identifiers of members in the basic group.
		**/
		public long[] memberUserIds;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 795404060;

		/**
		 * A newly created basic group.
		**/
		public MessageBasicGroupChatCreate() {}

		/**
		 * A newly created basic group.
		 *
		 * @param title Title of the basic group.
		 * @param memberUserIds User identifiers of members in the basic group.
		**/
		public MessageBasicGroupChatCreate(String title, long[] memberUserIds) {
			this.title = title;
			this.memberUserIds = memberUserIds;
		}

		/**
		 * A newly created basic group.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageBasicGroupChatCreate(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				this.memberUserIds = new long[input.readInt()];
				for (int i = 0; i < this.memberUserIds.length; i++) {
					this.memberUserIds[i] = input.readLong();
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageBasicGroupChatCreate.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageBasicGroupChatCreate.CONSTRUCTOR);
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
			if (this.memberUserIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.memberUserIds.length);
				for (int i = 0; i < this.memberUserIds.length; i++) {
					output.writeLong(this.memberUserIds[i]);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageBasicGroupChatCreate messageBasicGroupChatCreate = (MessageBasicGroupChatCreate) o;
			if (this.title != messageBasicGroupChatCreate.title) {
				return false;
			}
			if (!Arrays.equals(this.memberUserIds, messageBasicGroupChatCreate.memberUserIds)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.title == null ? 0 : this.title.hashCode();
			result = result * 31 + (Arrays.hashCode(this.memberUserIds));
			return result;
		}
	}

	/**
	 * A newly created supergroup or channel.
	**/
	public static final class MessageSupergroupChatCreate extends MessageContent {


		/**
		 * Title of the supergroup or channel.
		**/
		public String title;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -434325733;

		/**
		 * A newly created supergroup or channel.
		**/
		public MessageSupergroupChatCreate() {}

		/**
		 * A newly created supergroup or channel.
		 *
		 * @param title Title of the supergroup or channel.
		**/
		public MessageSupergroupChatCreate(String title) {
			this.title = title;
		}

		/**
		 * A newly created supergroup or channel.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageSupergroupChatCreate(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageSupergroupChatCreate.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageSupergroupChatCreate.CONSTRUCTOR);
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageSupergroupChatCreate messageSupergroupChatCreate = (MessageSupergroupChatCreate) o;
			if (this.title != messageSupergroupChatCreate.title) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.title == null ? 0 : this.title.hashCode();
		}
	}

	/**
	 * An updated chat title.
	**/
	public static final class MessageChatChangeTitle extends MessageContent {


		/**
		 * New chat title.
		**/
		public String title;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 748272449;

		/**
		 * An updated chat title.
		**/
		public MessageChatChangeTitle() {}

		/**
		 * An updated chat title.
		 *
		 * @param title New chat title.
		**/
		public MessageChatChangeTitle(String title) {
			this.title = title;
		}

		/**
		 * An updated chat title.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageChatChangeTitle(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageChatChangeTitle.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageChatChangeTitle.CONSTRUCTOR);
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageChatChangeTitle messageChatChangeTitle = (MessageChatChangeTitle) o;
			if (this.title != messageChatChangeTitle.title) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.title == null ? 0 : this.title.hashCode();
		}
	}

	/**
	 * An updated chat photo.
	**/
	public static final class MessageChatChangePhoto extends MessageContent {


		/**
		 * New chat photo.
		**/
		public ChatPhoto photo;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -813415093;

		/**
		 * An updated chat photo.
		**/
		public MessageChatChangePhoto() {}

		/**
		 * An updated chat photo.
		 *
		 * @param photo New chat photo.
		**/
		public MessageChatChangePhoto(ChatPhoto photo) {
			this.photo = photo;
		}

		/**
		 * An updated chat photo.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageChatChangePhoto(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (ChatPhoto.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.photo = new ChatPhoto(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageChatChangePhoto.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageChatChangePhoto.CONSTRUCTOR);
			if (this.photo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.photo.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageChatChangePhoto messageChatChangePhoto = (MessageChatChangePhoto) o;
			if (!Objects.equals(this.photo, messageChatChangePhoto.photo)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.photo == null ? 0 : this.photo.hashCode();
		}
	}

	/**
	 * A deleted chat photo.
	**/
	public static final class MessageChatDeletePhoto extends MessageContent {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -184374809;

		/**
		 * A deleted chat photo.
		**/
		public MessageChatDeletePhoto() {}

		/**
		 * A deleted chat photo.
		 *
		**/

		/**
		 * A deleted chat photo.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageChatDeletePhoto(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageChatDeletePhoto.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageChatDeletePhoto.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return MessageChatDeletePhoto.CONSTRUCTOR;
		}
	}

	/**
	 * New chat members were added.
	**/
	public static final class MessageChatAddMembers extends MessageContent {


		/**
		 * User identifiers of the new members.
		**/
		public long[] memberUserIds;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1701117908;

		/**
		 * New chat members were added.
		**/
		public MessageChatAddMembers() {}

		/**
		 * New chat members were added.
		 *
		 * @param memberUserIds User identifiers of the new members.
		**/
		public MessageChatAddMembers(long[] memberUserIds) {
			this.memberUserIds = memberUserIds;
		}

		/**
		 * New chat members were added.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageChatAddMembers(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.memberUserIds = new long[input.readInt()];
				for (int i = 0; i < this.memberUserIds.length; i++) {
					this.memberUserIds[i] = input.readLong();
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageChatAddMembers.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageChatAddMembers.CONSTRUCTOR);
			if (this.memberUserIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.memberUserIds.length);
				for (int i = 0; i < this.memberUserIds.length; i++) {
					output.writeLong(this.memberUserIds[i]);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageChatAddMembers messageChatAddMembers = (MessageChatAddMembers) o;
			if (!Arrays.equals(this.memberUserIds, messageChatAddMembers.memberUserIds)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.memberUserIds);
		}
	}

	/**
	 * A new member joined the chat via an invite link.
	**/
	public static final class MessageChatJoinByLink extends MessageContent {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1846493311;

		/**
		 * A new member joined the chat via an invite link.
		**/
		public MessageChatJoinByLink() {}

		/**
		 * A new member joined the chat via an invite link.
		 *
		**/

		/**
		 * A new member joined the chat via an invite link.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageChatJoinByLink(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageChatJoinByLink.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageChatJoinByLink.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return MessageChatJoinByLink.CONSTRUCTOR;
		}
	}

	/**
	 * A new member was accepted to the chat by an administrator.
	**/
	public static final class MessageChatJoinByRequest extends MessageContent {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1195428732;

		/**
		 * A new member was accepted to the chat by an administrator.
		**/
		public MessageChatJoinByRequest() {}

		/**
		 * A new member was accepted to the chat by an administrator.
		 *
		**/

		/**
		 * A new member was accepted to the chat by an administrator.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageChatJoinByRequest(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageChatJoinByRequest.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageChatJoinByRequest.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return MessageChatJoinByRequest.CONSTRUCTOR;
		}
	}

	/**
	 * A chat member was deleted.
	**/
	public static final class MessageChatDeleteMember extends MessageContent {


		/**
		 * User identifier of the deleted chat member.
		**/
		public long userId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 938029481;

		/**
		 * A chat member was deleted.
		**/
		public MessageChatDeleteMember() {}

		/**
		 * A chat member was deleted.
		 *
		 * @param userId User identifier of the deleted chat member.
		**/
		public MessageChatDeleteMember(long userId) {
			this.userId = userId;
		}

		/**
		 * A chat member was deleted.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageChatDeleteMember(DataInput input) throws IOException {
			this.userId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageChatDeleteMember.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageChatDeleteMember.CONSTRUCTOR);
			output.writeLong(this.userId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageChatDeleteMember messageChatDeleteMember = (MessageChatDeleteMember) o;
			if (this.userId != messageChatDeleteMember.userId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.userId);
		}
	}

	/**
	 * A basic group was upgraded to a supergroup and was deactivated as the
	 * result.
	**/
	public static final class MessageChatUpgradeTo extends MessageContent {


		/**
		 * Identifier of the supergroup to which the basic group was upgraded.
		**/
		public long supergroupId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 104813723;

		/**
		 * A basic group was upgraded to a supergroup and was deactivated as the result.
		**/
		public MessageChatUpgradeTo() {}

		/**
		 * A basic group was upgraded to a supergroup and was deactivated as the result.
		 *
		 * @param supergroupId Identifier of the supergroup to which the basic group was upgraded.
		**/
		public MessageChatUpgradeTo(long supergroupId) {
			this.supergroupId = supergroupId;
		}

		/**
		 * A basic group was upgraded to a supergroup and was deactivated as the result.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageChatUpgradeTo(DataInput input) throws IOException {
			this.supergroupId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageChatUpgradeTo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageChatUpgradeTo.CONSTRUCTOR);
			output.writeLong(this.supergroupId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageChatUpgradeTo messageChatUpgradeTo = (MessageChatUpgradeTo) o;
			if (this.supergroupId != messageChatUpgradeTo.supergroupId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.supergroupId);
		}
	}

	/**
	 * A supergroup has been created from a basic group.
	**/
	public static final class MessageChatUpgradeFrom extends MessageContent {


		/**
		 * Title of the newly created supergroup.
		**/
		public String title;

		/**
		 * The identifier of the original basic group.
		**/
		public long basicGroupId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 325954268;

		/**
		 * A supergroup has been created from a basic group.
		**/
		public MessageChatUpgradeFrom() {}

		/**
		 * A supergroup has been created from a basic group.
		 *
		 * @param title Title of the newly created supergroup.
		 * @param basicGroupId The identifier of the original basic group.
		**/
		public MessageChatUpgradeFrom(String title, long basicGroupId) {
			this.title = title;
			this.basicGroupId = basicGroupId;
		}

		/**
		 * A supergroup has been created from a basic group.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageChatUpgradeFrom(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
			this.basicGroupId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageChatUpgradeFrom.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageChatUpgradeFrom.CONSTRUCTOR);
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
			output.writeLong(this.basicGroupId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageChatUpgradeFrom messageChatUpgradeFrom = (MessageChatUpgradeFrom) o;
			if (this.title != messageChatUpgradeFrom.title) {
				return false;
			}
			if (this.basicGroupId != messageChatUpgradeFrom.basicGroupId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.basicGroupId);
			result = result * 31 + (this.title == null ? 0 : this.title.hashCode());
			return result;
		}
	}

	/**
	 * A message has been pinned.
	**/
	public static final class MessagePinMessage extends MessageContent {


		/**
		 * Identifier of the pinned message, can be an identifier of a deleted message or 0.
		**/
		public long messageId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 953503801;

		/**
		 * A message has been pinned.
		**/
		public MessagePinMessage() {}

		/**
		 * A message has been pinned.
		 *
		 * @param messageId Identifier of the pinned message, can be an identifier of a deleted message or 0.
		**/
		public MessagePinMessage(long messageId) {
			this.messageId = messageId;
		}

		/**
		 * A message has been pinned.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessagePinMessage(DataInput input) throws IOException {
			this.messageId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessagePinMessage.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessagePinMessage.CONSTRUCTOR);
			output.writeLong(this.messageId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessagePinMessage messagePinMessage = (MessagePinMessage) o;
			if (this.messageId != messagePinMessage.messageId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.messageId);
		}
	}

	/**
	 * A screenshot of a message in the chat has been taken.
	**/
	public static final class MessageScreenshotTaken extends MessageContent {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1564971605;

		/**
		 * A screenshot of a message in the chat has been taken.
		**/
		public MessageScreenshotTaken() {}

		/**
		 * A screenshot of a message in the chat has been taken.
		 *
		**/

		/**
		 * A screenshot of a message in the chat has been taken.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageScreenshotTaken(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageScreenshotTaken.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageScreenshotTaken.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return MessageScreenshotTaken.CONSTRUCTOR;
		}
	}

	/**
	 * A new background was set in the chat.
	**/
	public static final class MessageChatSetBackground extends MessageContent {


		/**
		 * Identifier of the message with a previously set same background; 0 if none. Can be an identifier of a deleted message.
		**/
		public long oldBackgroundMessageId;

		/**
		 * The new background.
		**/
		public ChatBackground background;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2122213583;

		/**
		 * A new background was set in the chat.
		**/
		public MessageChatSetBackground() {}

		/**
		 * A new background was set in the chat.
		 *
		 * @param oldBackgroundMessageId Identifier of the message with a previously set same background; 0 if none. Can be an identifier of a deleted message.
		 * @param background The new background.
		**/
		public MessageChatSetBackground(long oldBackgroundMessageId, ChatBackground background) {
			this.oldBackgroundMessageId = oldBackgroundMessageId;
			this.background = background;
		}

		/**
		 * A new background was set in the chat.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageChatSetBackground(DataInput input) throws IOException {
			this.oldBackgroundMessageId = input.readLong();
			if (input.readBoolean()) {
				if (ChatBackground.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.background = new ChatBackground(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageChatSetBackground.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageChatSetBackground.CONSTRUCTOR);
			output.writeLong(this.oldBackgroundMessageId);
			if (this.background == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.background.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageChatSetBackground messageChatSetBackground = (MessageChatSetBackground) o;
			if (this.oldBackgroundMessageId != messageChatSetBackground.oldBackgroundMessageId) {
				return false;
			}
			if (!Objects.equals(this.background, messageChatSetBackground.background)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.oldBackgroundMessageId);
			result = result * 31 + (this.background == null ? 0 : this.background.hashCode());
			return result;
		}
	}

	/**
	 * A theme in the chat has been changed.
	**/
	public static final class MessageChatSetTheme extends MessageContent {


		/**
		 * If non-empty, name of a new theme, set for the chat. Otherwise, chat theme was reset to the default one.
		**/
		public String themeName;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1716612088;

		/**
		 * A theme in the chat has been changed.
		**/
		public MessageChatSetTheme() {}

		/**
		 * A theme in the chat has been changed.
		 *
		 * @param themeName If non-empty, name of a new theme, set for the chat. Otherwise, chat theme was reset to the default one.
		**/
		public MessageChatSetTheme(String themeName) {
			this.themeName = themeName;
		}

		/**
		 * A theme in the chat has been changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageChatSetTheme(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] themeNameTmp = new byte[input.readInt()];
				input.readFully(themeNameTmp);
				this.themeName = new String(themeNameTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageChatSetTheme.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageChatSetTheme.CONSTRUCTOR);
			if (this.themeName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] themeNameTmp = this.themeName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(themeNameTmp.length);
				output.write(themeNameTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageChatSetTheme messageChatSetTheme = (MessageChatSetTheme) o;
			if (this.themeName != messageChatSetTheme.themeName) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.themeName == null ? 0 : this.themeName.hashCode();
		}
	}

	/**
	 * The auto-delete or self-destruct timer for messages in the chat has
	 * been changed.
	**/
	public static final class MessageChatSetMessageAutoDeleteTime extends MessageContent {


		/**
		 * New value auto-delete or self-destruct time, in seconds; 0 if disabled.
		**/
		public int messageAutoDeleteTime;

		/**
		 * If not 0, a user identifier, which default setting was automatically applied.
		**/
		public long fromUserId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1637745966;

		/**
		 * The auto-delete or self-destruct timer for messages in the chat has been changed.
		**/
		public MessageChatSetMessageAutoDeleteTime() {}

		/**
		 * The auto-delete or self-destruct timer for messages in the chat has been changed.
		 *
		 * @param messageAutoDeleteTime New value auto-delete or self-destruct time, in seconds; 0 if disabled.
		 * @param fromUserId If not 0, a user identifier, which default setting was automatically applied.
		**/
		public MessageChatSetMessageAutoDeleteTime(int messageAutoDeleteTime, long fromUserId) {
			this.messageAutoDeleteTime = messageAutoDeleteTime;
			this.fromUserId = fromUserId;
		}

		/**
		 * The auto-delete or self-destruct timer for messages in the chat has been changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageChatSetMessageAutoDeleteTime(DataInput input) throws IOException {
			this.messageAutoDeleteTime = input.readInt();
			this.fromUserId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageChatSetMessageAutoDeleteTime.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageChatSetMessageAutoDeleteTime.CONSTRUCTOR);
			output.writeInt(this.messageAutoDeleteTime);
			output.writeLong(this.fromUserId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageChatSetMessageAutoDeleteTime messageChatSetMessageAutoDeleteTime = (MessageChatSetMessageAutoDeleteTime) o;
			if (this.messageAutoDeleteTime != messageChatSetMessageAutoDeleteTime.messageAutoDeleteTime) {
				return false;
			}
			if (this.fromUserId != messageChatSetMessageAutoDeleteTime.fromUserId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.messageAutoDeleteTime);
			return result;
		}
	}

	/**
	 * A forum topic has been created.
	**/
	public static final class MessageForumTopicCreated extends MessageContent {


		/**
		 * Name of the topic.
		**/
		public String name;

		/**
		 * Icon of the topic.
		**/
		public ForumTopicIcon icon;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1194440751;

		/**
		 * A forum topic has been created.
		**/
		public MessageForumTopicCreated() {}

		/**
		 * A forum topic has been created.
		 *
		 * @param name Name of the topic.
		 * @param icon Icon of the topic.
		**/
		public MessageForumTopicCreated(String name, ForumTopicIcon icon) {
			this.name = name;
			this.icon = icon;
		}

		/**
		 * A forum topic has been created.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageForumTopicCreated(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] nameTmp = new byte[input.readInt()];
				input.readFully(nameTmp);
				this.name = new String(nameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (ForumTopicIcon.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.icon = new ForumTopicIcon(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageForumTopicCreated.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageForumTopicCreated.CONSTRUCTOR);
			if (this.name == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nameTmp = this.name.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nameTmp.length);
				output.write(nameTmp);
			}
			if (this.icon == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.icon.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageForumTopicCreated messageForumTopicCreated = (MessageForumTopicCreated) o;
			if (this.name != messageForumTopicCreated.name) {
				return false;
			}
			if (!Objects.equals(this.icon, messageForumTopicCreated.icon)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.name == null ? 0 : this.name.hashCode();
			result = result * 31 + (this.icon == null ? 0 : this.icon.hashCode());
			return result;
		}
	}

	/**
	 * A forum topic has been edited.
	**/
	public static final class MessageForumTopicEdited extends MessageContent {


		/**
		 * If non-empty, the new name of the topic.
		**/
		public String name;

		/**
		 * True, if icon&#039;s customEmojiId is changed.
		**/
		public boolean editIconCustomEmojiId;

		/**
		 * New unique identifier of the custom emoji shown on the topic icon; 0 if none. Must be ignored if editIconCustomEmojiId is false.
		**/
		public long iconCustomEmojiId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 12629888;

		/**
		 * A forum topic has been edited.
		**/
		public MessageForumTopicEdited() {}

		/**
		 * A forum topic has been edited.
		 *
		 * @param name If non-empty, the new name of the topic.
		 * @param editIconCustomEmojiId True, if icon&#039;s customEmojiId is changed.
		 * @param iconCustomEmojiId New unique identifier of the custom emoji shown on the topic icon; 0 if none. Must be ignored if editIconCustomEmojiId is false.
		**/
		public MessageForumTopicEdited(String name,
				boolean editIconCustomEmojiId,
				long iconCustomEmojiId) {
			this.name = name;
			this.editIconCustomEmojiId = editIconCustomEmojiId;
			this.iconCustomEmojiId = iconCustomEmojiId;
		}

		/**
		 * A forum topic has been edited.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageForumTopicEdited(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] nameTmp = new byte[input.readInt()];
				input.readFully(nameTmp);
				this.name = new String(nameTmp, StandardCharsets.UTF_8);
			}
			this.editIconCustomEmojiId = input.readBoolean();
			this.iconCustomEmojiId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageForumTopicEdited.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageForumTopicEdited.CONSTRUCTOR);
			if (this.name == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nameTmp = this.name.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nameTmp.length);
				output.write(nameTmp);
			}
			output.writeBoolean(this.editIconCustomEmojiId);
			output.writeLong(this.iconCustomEmojiId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageForumTopicEdited messageForumTopicEdited = (MessageForumTopicEdited) o;
			if (this.name != messageForumTopicEdited.name) {
				return false;
			}
			if (this.editIconCustomEmojiId != messageForumTopicEdited.editIconCustomEmojiId) {
				return false;
			}
			if (this.iconCustomEmojiId != messageForumTopicEdited.iconCustomEmojiId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.editIconCustomEmojiId);
			result = result * 31 + (this.name == null ? 0 : this.name.hashCode());
			return result;
		}
	}

	/**
	 * A forum topic has been closed or opened.
	**/
	public static final class MessageForumTopicIsClosedToggled extends MessageContent {


		/**
		 * True, if the topic was closed; otherwise, the topic was reopened.
		**/
		public boolean isClosed;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1264029664;

		/**
		 * A forum topic has been closed or opened.
		**/
		public MessageForumTopicIsClosedToggled() {}

		/**
		 * A forum topic has been closed or opened.
		 *
		 * @param isClosed True, if the topic was closed; otherwise, the topic was reopened.
		**/
		public MessageForumTopicIsClosedToggled(boolean isClosed) {
			this.isClosed = isClosed;
		}

		/**
		 * A forum topic has been closed or opened.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageForumTopicIsClosedToggled(DataInput input) throws IOException {
			this.isClosed = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageForumTopicIsClosedToggled.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageForumTopicIsClosedToggled.CONSTRUCTOR);
			output.writeBoolean(this.isClosed);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageForumTopicIsClosedToggled messageForumTopicIsClosedToggled = (MessageForumTopicIsClosedToggled) o;
			if (this.isClosed != messageForumTopicIsClosedToggled.isClosed) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Boolean.hashCode(this.isClosed);
		}
	}

	/**
	 * A General forum topic has been hidden or unhidden.
	**/
	public static final class MessageForumTopicIsHiddenToggled extends MessageContent {


		/**
		 * True, if the topic was hidden; otherwise, the topic was unhidden.
		**/
		public boolean isHidden;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1751936002;

		/**
		 * A General forum topic has been hidden or unhidden.
		**/
		public MessageForumTopicIsHiddenToggled() {}

		/**
		 * A General forum topic has been hidden or unhidden.
		 *
		 * @param isHidden True, if the topic was hidden; otherwise, the topic was unhidden.
		**/
		public MessageForumTopicIsHiddenToggled(boolean isHidden) {
			this.isHidden = isHidden;
		}

		/**
		 * A General forum topic has been hidden or unhidden.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageForumTopicIsHiddenToggled(DataInput input) throws IOException {
			this.isHidden = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageForumTopicIsHiddenToggled.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageForumTopicIsHiddenToggled.CONSTRUCTOR);
			output.writeBoolean(this.isHidden);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageForumTopicIsHiddenToggled messageForumTopicIsHiddenToggled = (MessageForumTopicIsHiddenToggled) o;
			if (this.isHidden != messageForumTopicIsHiddenToggled.isHidden) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Boolean.hashCode(this.isHidden);
		}
	}

	/**
	 * A profile photo was suggested to a user in a private chat.
	**/
	public static final class MessageSuggestProfilePhoto extends MessageContent {


		/**
		 * The suggested chat photo. Use the method setProfilePhoto with inputChatPhotoPrevious to apply the photo.
		**/
		public ChatPhoto photo;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1251926297;

		/**
		 * A profile photo was suggested to a user in a private chat.
		**/
		public MessageSuggestProfilePhoto() {}

		/**
		 * A profile photo was suggested to a user in a private chat.
		 *
		 * @param photo The suggested chat photo. Use the method setProfilePhoto with inputChatPhotoPrevious to apply the photo.
		**/
		public MessageSuggestProfilePhoto(ChatPhoto photo) {
			this.photo = photo;
		}

		/**
		 * A profile photo was suggested to a user in a private chat.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageSuggestProfilePhoto(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (ChatPhoto.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.photo = new ChatPhoto(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageSuggestProfilePhoto.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageSuggestProfilePhoto.CONSTRUCTOR);
			if (this.photo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.photo.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageSuggestProfilePhoto messageSuggestProfilePhoto = (MessageSuggestProfilePhoto) o;
			if (!Objects.equals(this.photo, messageSuggestProfilePhoto.photo)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.photo == null ? 0 : this.photo.hashCode();
		}
	}

	/**
	 * A non-standard action has happened in the chat.
	**/
	public static final class MessageCustomServiceAction extends MessageContent {


		/**
		 * Message text to be shown in the chat.
		**/
		public String text;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1435879282;

		/**
		 * A non-standard action has happened in the chat.
		**/
		public MessageCustomServiceAction() {}

		/**
		 * A non-standard action has happened in the chat.
		 *
		 * @param text Message text to be shown in the chat.
		**/
		public MessageCustomServiceAction(String text) {
			this.text = text;
		}

		/**
		 * A non-standard action has happened in the chat.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageCustomServiceAction(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] textTmp = new byte[input.readInt()];
				input.readFully(textTmp);
				this.text = new String(textTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageCustomServiceAction.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageCustomServiceAction.CONSTRUCTOR);
			if (this.text == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] textTmp = this.text.getBytes(StandardCharsets.UTF_8);
				output.writeInt(textTmp.length);
				output.write(textTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageCustomServiceAction messageCustomServiceAction = (MessageCustomServiceAction) o;
			if (this.text != messageCustomServiceAction.text) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.text == null ? 0 : this.text.hashCode();
		}
	}

	/**
	 * A new high score was achieved in a game.
	**/
	public static final class MessageGameScore extends MessageContent {


		/**
		 * Identifier of the message with the game, can be an identifier of a deleted message.
		**/
		public long gameMessageId;

		/**
		 * Identifier of the game; may be different from the games presented in the message with the game.
		**/
		public long gameId;

		/**
		 * New score.
		**/
		public int score;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1344904575;

		/**
		 * A new high score was achieved in a game.
		**/
		public MessageGameScore() {}

		/**
		 * A new high score was achieved in a game.
		 *
		 * @param gameMessageId Identifier of the message with the game, can be an identifier of a deleted message.
		 * @param gameId Identifier of the game; may be different from the games presented in the message with the game.
		 * @param score New score.
		**/
		public MessageGameScore(long gameMessageId, long gameId, int score) {
			this.gameMessageId = gameMessageId;
			this.gameId = gameId;
			this.score = score;
		}

		/**
		 * A new high score was achieved in a game.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageGameScore(DataInput input) throws IOException {
			this.gameMessageId = input.readLong();
			this.gameId = input.readLong();
			this.score = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageGameScore.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageGameScore.CONSTRUCTOR);
			output.writeLong(this.gameMessageId);
			output.writeLong(this.gameId);
			output.writeInt(this.score);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageGameScore messageGameScore = (MessageGameScore) o;
			if (this.gameMessageId != messageGameScore.gameMessageId) {
				return false;
			}
			if (this.gameId != messageGameScore.gameId) {
				return false;
			}
			if (this.score != messageGameScore.score) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.gameMessageId);
			return result;
		}
	}

	/**
	 * A payment has been completed.
	**/
	public static final class MessagePaymentSuccessful extends MessageContent {


		/**
		 * Identifier of the chat, containing the corresponding invoice message.
		**/
		public long invoiceChatId;

		/**
		 * Identifier of the message with the corresponding invoice; can be 0 or an identifier of a deleted message.
		**/
		public long invoiceMessageId;

		/**
		 * Currency for the price of the product.
		**/
		public String currency;

		/**
		 * Total price for the product, in the smallest units of the currency.
		**/
		public long totalAmount;

		/**
		 * True, if this is a recurring payment.
		**/
		public boolean isRecurring;

		/**
		 * True, if this is the first recurring payment.
		**/
		public boolean isFirstRecurring;

		/**
		 * Name of the invoice; may be empty if unknown.
		**/
		public String invoiceName;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1406745820;

		/**
		 * A payment has been completed.
		**/
		public MessagePaymentSuccessful() {}

		/**
		 * A payment has been completed.
		 *
		 * @param invoiceChatId Identifier of the chat, containing the corresponding invoice message.
		 * @param invoiceMessageId Identifier of the message with the corresponding invoice; can be 0 or an identifier of a deleted message.
		 * @param currency Currency for the price of the product.
		 * @param totalAmount Total price for the product, in the smallest units of the currency.
		 * @param isRecurring True, if this is a recurring payment.
		 * @param isFirstRecurring True, if this is the first recurring payment.
		 * @param invoiceName Name of the invoice; may be empty if unknown.
		**/
		public MessagePaymentSuccessful(long invoiceChatId,
				long invoiceMessageId,
				String currency,
				long totalAmount,
				boolean isRecurring,
				boolean isFirstRecurring,
				String invoiceName) {
			this.invoiceChatId = invoiceChatId;
			this.invoiceMessageId = invoiceMessageId;
			this.currency = currency;
			this.totalAmount = totalAmount;
			this.isRecurring = isRecurring;
			this.isFirstRecurring = isFirstRecurring;
			this.invoiceName = invoiceName;
		}

		/**
		 * A payment has been completed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessagePaymentSuccessful(DataInput input) throws IOException {
			this.invoiceChatId = input.readLong();
			this.invoiceMessageId = input.readLong();
			if (input.readBoolean()) {
				byte[] currencyTmp = new byte[input.readInt()];
				input.readFully(currencyTmp);
				this.currency = new String(currencyTmp, StandardCharsets.UTF_8);
			}
			this.totalAmount = input.readLong();
			this.isRecurring = input.readBoolean();
			this.isFirstRecurring = input.readBoolean();
			if (input.readBoolean()) {
				byte[] invoiceNameTmp = new byte[input.readInt()];
				input.readFully(invoiceNameTmp);
				this.invoiceName = new String(invoiceNameTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessagePaymentSuccessful.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessagePaymentSuccessful.CONSTRUCTOR);
			output.writeLong(this.invoiceChatId);
			output.writeLong(this.invoiceMessageId);
			if (this.currency == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] currencyTmp = this.currency.getBytes(StandardCharsets.UTF_8);
				output.writeInt(currencyTmp.length);
				output.write(currencyTmp);
			}
			output.writeLong(this.totalAmount);
			output.writeBoolean(this.isRecurring);
			output.writeBoolean(this.isFirstRecurring);
			if (this.invoiceName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] invoiceNameTmp = this.invoiceName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(invoiceNameTmp.length);
				output.write(invoiceNameTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessagePaymentSuccessful messagePaymentSuccessful = (MessagePaymentSuccessful) o;
			if (this.invoiceChatId != messagePaymentSuccessful.invoiceChatId) {
				return false;
			}
			if (this.invoiceMessageId != messagePaymentSuccessful.invoiceMessageId) {
				return false;
			}
			if (this.currency != messagePaymentSuccessful.currency) {
				return false;
			}
			if (this.totalAmount != messagePaymentSuccessful.totalAmount) {
				return false;
			}
			if (this.isRecurring != messagePaymentSuccessful.isRecurring) {
				return false;
			}
			if (this.isFirstRecurring != messagePaymentSuccessful.isFirstRecurring) {
				return false;
			}
			if (this.invoiceName != messagePaymentSuccessful.invoiceName) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.invoiceChatId);
			result = result * 31 + (this.currency == null ? 0 : this.currency.hashCode());
			result = result * 31 + (this.invoiceName == null ? 0 : this.invoiceName.hashCode());
			return result;
		}
	}

	/**
	 * A payment has been completed; for bots only.
	**/
	public static final class MessagePaymentSuccessfulBot extends MessageContent {


		/**
		 * Currency for price of the product.
		**/
		public String currency;

		/**
		 * Total price for the product, in the smallest units of the currency.
		**/
		public long totalAmount;

		/**
		 * True, if this is a recurring payment.
		**/
		public boolean isRecurring;

		/**
		 * True, if this is the first recurring payment.
		**/
		public boolean isFirstRecurring;

		/**
		 * Invoice payload.
		**/
		public byte[] invoicePayload;

		/**
		 * Identifier of the shipping option chosen by the user; may be empty if not applicable.
		**/
		public String shippingOptionId;

		/**
		 * Information about the order; may be null.
		**/
		public OrderInfo orderInfo;

		/**
		 * Telegram payment identifier.
		**/
		public String telegramPaymentChargeId;

		/**
		 * Provider payment identifier.
		**/
		public String providerPaymentChargeId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1759592121;

		/**
		 * A payment has been completed; for bots only.
		**/
		public MessagePaymentSuccessfulBot() {}

		/**
		 * A payment has been completed; for bots only.
		 *
		 * @param currency Currency for price of the product.
		 * @param totalAmount Total price for the product, in the smallest units of the currency.
		 * @param isRecurring True, if this is a recurring payment.
		 * @param isFirstRecurring True, if this is the first recurring payment.
		 * @param invoicePayload Invoice payload.
		 * @param shippingOptionId Identifier of the shipping option chosen by the user; may be empty if not applicable.
		 * @param orderInfo Information about the order; may be null.
		 * @param telegramPaymentChargeId Telegram payment identifier.
		 * @param providerPaymentChargeId Provider payment identifier.
		**/
		public MessagePaymentSuccessfulBot(String currency,
				long totalAmount,
				boolean isRecurring,
				boolean isFirstRecurring,
				byte[] invoicePayload,
				String shippingOptionId,
				OrderInfo orderInfo,
				String telegramPaymentChargeId,
				String providerPaymentChargeId) {
			this.currency = currency;
			this.totalAmount = totalAmount;
			this.isRecurring = isRecurring;
			this.isFirstRecurring = isFirstRecurring;
			this.invoicePayload = invoicePayload;
			this.shippingOptionId = shippingOptionId;
			this.orderInfo = orderInfo;
			this.telegramPaymentChargeId = telegramPaymentChargeId;
			this.providerPaymentChargeId = providerPaymentChargeId;
		}

		/**
		 * A payment has been completed; for bots only.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessagePaymentSuccessfulBot(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] currencyTmp = new byte[input.readInt()];
				input.readFully(currencyTmp);
				this.currency = new String(currencyTmp, StandardCharsets.UTF_8);
			}
			this.totalAmount = input.readLong();
			this.isRecurring = input.readBoolean();
			this.isFirstRecurring = input.readBoolean();
			if (input.readBoolean()) {
				this.invoicePayload = new byte[input.readInt()];
				input.readFully(this.invoicePayload);
			}
			if (input.readBoolean()) {
				byte[] shippingOptionIdTmp = new byte[input.readInt()];
				input.readFully(shippingOptionIdTmp);
				this.shippingOptionId = new String(shippingOptionIdTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (OrderInfo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.orderInfo = new OrderInfo(input);
			}
			if (input.readBoolean()) {
				byte[] telegramPaymentChargeIdTmp = new byte[input.readInt()];
				input.readFully(telegramPaymentChargeIdTmp);
				this.telegramPaymentChargeId = new String(telegramPaymentChargeIdTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] providerPaymentChargeIdTmp = new byte[input.readInt()];
				input.readFully(providerPaymentChargeIdTmp);
				this.providerPaymentChargeId = new String(providerPaymentChargeIdTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessagePaymentSuccessfulBot.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessagePaymentSuccessfulBot.CONSTRUCTOR);
			if (this.currency == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] currencyTmp = this.currency.getBytes(StandardCharsets.UTF_8);
				output.writeInt(currencyTmp.length);
				output.write(currencyTmp);
			}
			output.writeLong(this.totalAmount);
			output.writeBoolean(this.isRecurring);
			output.writeBoolean(this.isFirstRecurring);
			if (this.invoicePayload == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.invoicePayload.length);
				output.write(this.invoicePayload);
			}
			if (this.shippingOptionId == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] shippingOptionIdTmp = this.shippingOptionId.getBytes(StandardCharsets.UTF_8);
				output.writeInt(shippingOptionIdTmp.length);
				output.write(shippingOptionIdTmp);
			}
			if (this.orderInfo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.orderInfo.serialize(output);
			}
			if (this.telegramPaymentChargeId == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] telegramPaymentChargeIdTmp = this.telegramPaymentChargeId.getBytes(StandardCharsets.UTF_8);
				output.writeInt(telegramPaymentChargeIdTmp.length);
				output.write(telegramPaymentChargeIdTmp);
			}
			if (this.providerPaymentChargeId == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] providerPaymentChargeIdTmp = this.providerPaymentChargeId.getBytes(StandardCharsets.UTF_8);
				output.writeInt(providerPaymentChargeIdTmp.length);
				output.write(providerPaymentChargeIdTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessagePaymentSuccessfulBot messagePaymentSuccessfulBot = (MessagePaymentSuccessfulBot) o;
			if (this.currency != messagePaymentSuccessfulBot.currency) {
				return false;
			}
			if (this.totalAmount != messagePaymentSuccessfulBot.totalAmount) {
				return false;
			}
			if (this.isRecurring != messagePaymentSuccessfulBot.isRecurring) {
				return false;
			}
			if (this.isFirstRecurring != messagePaymentSuccessfulBot.isFirstRecurring) {
				return false;
			}
			if (this.invoicePayload != messagePaymentSuccessfulBot.invoicePayload) {
				return false;
			}
			if (this.shippingOptionId != messagePaymentSuccessfulBot.shippingOptionId) {
				return false;
			}
			if (!Objects.equals(this.orderInfo, messagePaymentSuccessfulBot.orderInfo)) {
				return false;
			}
			if (this.telegramPaymentChargeId != messagePaymentSuccessfulBot.telegramPaymentChargeId) {
				return false;
			}
			if (this.providerPaymentChargeId != messagePaymentSuccessfulBot.providerPaymentChargeId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.totalAmount);
			result = result * 31 + (this.currency == null ? 0 : this.currency.hashCode());
			result = result * 31 + (Arrays.hashCode(this.invoicePayload));
			result = result * 31 + (this.shippingOptionId == null ? 0 : this.shippingOptionId.hashCode());
			result = result * 31 + (this.orderInfo == null ? 0 : this.orderInfo.hashCode());
			result = result * 31 + (this.telegramPaymentChargeId == null ? 0 : this.telegramPaymentChargeId.hashCode());
			result = result * 31 + (this.providerPaymentChargeId == null ? 0 : this.providerPaymentChargeId.hashCode());
			return result;
		}
	}

	/**
	 * Telegram Premium was gifted to the user.
	**/
	public static final class MessageGiftedPremium extends MessageContent {


		/**
		 * The identifier of a user that gifted Telegram Premium; 0 if the gift was anonymous.
		**/
		public long gifterUserId;

		/**
		 * Currency for the paid amount.
		**/
		public String currency;

		/**
		 * The paid amount, in the smallest units of the currency.
		**/
		public long amount;

		/**
		 * Cryptocurrency used to pay for the gift; may be empty if none.
		**/
		public String cryptocurrency;

		/**
		 * The paid amount, in the smallest units of the cryptocurrency.
		**/
		public long cryptocurrencyAmount;

		/**
		 * Number of month the Telegram Premium subscription will be active.
		**/
		public int monthCount;

		/**
		 * A sticker to be shown in the message; may be null if unknown.
		**/
		public Sticker sticker;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 126688522;

		/**
		 * Telegram Premium was gifted to the user.
		**/
		public MessageGiftedPremium() {}

		/**
		 * Telegram Premium was gifted to the user.
		 *
		 * @param gifterUserId The identifier of a user that gifted Telegram Premium; 0 if the gift was anonymous.
		 * @param currency Currency for the paid amount.
		 * @param amount The paid amount, in the smallest units of the currency.
		 * @param cryptocurrency Cryptocurrency used to pay for the gift; may be empty if none.
		 * @param cryptocurrencyAmount The paid amount, in the smallest units of the cryptocurrency.
		 * @param monthCount Number of month the Telegram Premium subscription will be active.
		 * @param sticker A sticker to be shown in the message; may be null if unknown.
		**/
		public MessageGiftedPremium(long gifterUserId,
				String currency,
				long amount,
				String cryptocurrency,
				long cryptocurrencyAmount,
				int monthCount,
				Sticker sticker) {
			this.gifterUserId = gifterUserId;
			this.currency = currency;
			this.amount = amount;
			this.cryptocurrency = cryptocurrency;
			this.cryptocurrencyAmount = cryptocurrencyAmount;
			this.monthCount = monthCount;
			this.sticker = sticker;
		}

		/**
		 * Telegram Premium was gifted to the user.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageGiftedPremium(DataInput input) throws IOException {
			this.gifterUserId = input.readLong();
			if (input.readBoolean()) {
				byte[] currencyTmp = new byte[input.readInt()];
				input.readFully(currencyTmp);
				this.currency = new String(currencyTmp, StandardCharsets.UTF_8);
			}
			this.amount = input.readLong();
			if (input.readBoolean()) {
				byte[] cryptocurrencyTmp = new byte[input.readInt()];
				input.readFully(cryptocurrencyTmp);
				this.cryptocurrency = new String(cryptocurrencyTmp, StandardCharsets.UTF_8);
			}
			this.cryptocurrencyAmount = input.readLong();
			this.monthCount = input.readInt();
			if (input.readBoolean()) {
				if (Sticker.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.sticker = new Sticker(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageGiftedPremium.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageGiftedPremium.CONSTRUCTOR);
			output.writeLong(this.gifterUserId);
			if (this.currency == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] currencyTmp = this.currency.getBytes(StandardCharsets.UTF_8);
				output.writeInt(currencyTmp.length);
				output.write(currencyTmp);
			}
			output.writeLong(this.amount);
			if (this.cryptocurrency == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] cryptocurrencyTmp = this.cryptocurrency.getBytes(StandardCharsets.UTF_8);
				output.writeInt(cryptocurrencyTmp.length);
				output.write(cryptocurrencyTmp);
			}
			output.writeLong(this.cryptocurrencyAmount);
			output.writeInt(this.monthCount);
			if (this.sticker == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.sticker.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageGiftedPremium messageGiftedPremium = (MessageGiftedPremium) o;
			if (this.gifterUserId != messageGiftedPremium.gifterUserId) {
				return false;
			}
			if (this.currency != messageGiftedPremium.currency) {
				return false;
			}
			if (this.amount != messageGiftedPremium.amount) {
				return false;
			}
			if (this.cryptocurrency != messageGiftedPremium.cryptocurrency) {
				return false;
			}
			if (this.cryptocurrencyAmount != messageGiftedPremium.cryptocurrencyAmount) {
				return false;
			}
			if (this.monthCount != messageGiftedPremium.monthCount) {
				return false;
			}
			if (!Objects.equals(this.sticker, messageGiftedPremium.sticker)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.gifterUserId);
			result = result * 31 + (this.currency == null ? 0 : this.currency.hashCode());
			result = result * 31 + (this.cryptocurrency == null ? 0 : this.cryptocurrency.hashCode());
			result = result * 31 + (this.sticker == null ? 0 : this.sticker.hashCode());
			return result;
		}
	}

	/**
	 * A contact has registered with Telegram.
	**/
	public static final class MessageContactRegistered extends MessageContent {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1502020353;

		/**
		 * A contact has registered with Telegram.
		**/
		public MessageContactRegistered() {}

		/**
		 * A contact has registered with Telegram.
		 *
		**/

		/**
		 * A contact has registered with Telegram.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageContactRegistered(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageContactRegistered.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageContactRegistered.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return MessageContactRegistered.CONSTRUCTOR;
		}
	}

	/**
	 * The current user shared a user, which was requested by the bot.
	**/
	public static final class MessageUserShared extends MessageContent {


		/**
		 * Identifier of the shared user.
		**/
		public long userId;

		/**
		 * Identifier of the keyboard button with the request.
		**/
		public int buttonId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -723732612;

		/**
		 * The current user shared a user, which was requested by the bot.
		**/
		public MessageUserShared() {}

		/**
		 * The current user shared a user, which was requested by the bot.
		 *
		 * @param userId Identifier of the shared user.
		 * @param buttonId Identifier of the keyboard button with the request.
		**/
		public MessageUserShared(long userId, int buttonId) {
			this.userId = userId;
			this.buttonId = buttonId;
		}

		/**
		 * The current user shared a user, which was requested by the bot.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageUserShared(DataInput input) throws IOException {
			this.userId = input.readLong();
			this.buttonId = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageUserShared.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageUserShared.CONSTRUCTOR);
			output.writeLong(this.userId);
			output.writeInt(this.buttonId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageUserShared messageUserShared = (MessageUserShared) o;
			if (this.userId != messageUserShared.userId) {
				return false;
			}
			if (this.buttonId != messageUserShared.buttonId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.userId);
			return result;
		}
	}

	/**
	 * The current user shared a chat, which was requested by the bot.
	**/
	public static final class MessageChatShared extends MessageContent {


		/**
		 * Identifier of the shared chat.
		**/
		public long chatId;

		/**
		 * Identifier of the keyboard button with the request.
		**/
		public int buttonId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 584806545;

		/**
		 * The current user shared a chat, which was requested by the bot.
		**/
		public MessageChatShared() {}

		/**
		 * The current user shared a chat, which was requested by the bot.
		 *
		 * @param chatId Identifier of the shared chat.
		 * @param buttonId Identifier of the keyboard button with the request.
		**/
		public MessageChatShared(long chatId, int buttonId) {
			this.chatId = chatId;
			this.buttonId = buttonId;
		}

		/**
		 * The current user shared a chat, which was requested by the bot.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageChatShared(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.buttonId = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageChatShared.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageChatShared.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeInt(this.buttonId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageChatShared messageChatShared = (MessageChatShared) o;
			if (this.chatId != messageChatShared.chatId) {
				return false;
			}
			if (this.buttonId != messageChatShared.buttonId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * The current user has connected a website by logging in using Telegram
	 * Login Widget on it.
	**/
	public static final class MessageWebsiteConnected extends MessageContent {


		/**
		 * Domain name of the connected website.
		**/
		public String domainName;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1074551800;

		/**
		 * The current user has connected a website by logging in using Telegram Login Widget on it.
		**/
		public MessageWebsiteConnected() {}

		/**
		 * The current user has connected a website by logging in using Telegram Login Widget on it.
		 *
		 * @param domainName Domain name of the connected website.
		**/
		public MessageWebsiteConnected(String domainName) {
			this.domainName = domainName;
		}

		/**
		 * The current user has connected a website by logging in using Telegram Login Widget on it.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageWebsiteConnected(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] domainNameTmp = new byte[input.readInt()];
				input.readFully(domainNameTmp);
				this.domainName = new String(domainNameTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageWebsiteConnected.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageWebsiteConnected.CONSTRUCTOR);
			if (this.domainName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] domainNameTmp = this.domainName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(domainNameTmp.length);
				output.write(domainNameTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageWebsiteConnected messageWebsiteConnected = (MessageWebsiteConnected) o;
			if (this.domainName != messageWebsiteConnected.domainName) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.domainName == null ? 0 : this.domainName.hashCode();
		}
	}

	/**
	 * The user allowed the bot to send messages.
	**/
	public static final class MessageBotWriteAccessAllowed extends MessageContent {


		/**
		 * Information about the Web App, which requested the access; may be null if none or the Web App was opened from the attachment menu.
		**/
		public WebApp webApp;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1055588088;

		/**
		 * The user allowed the bot to send messages.
		**/
		public MessageBotWriteAccessAllowed() {}

		/**
		 * The user allowed the bot to send messages.
		 *
		 * @param webApp Information about the Web App, which requested the access; may be null if none or the Web App was opened from the attachment menu.
		**/
		public MessageBotWriteAccessAllowed(WebApp webApp) {
			this.webApp = webApp;
		}

		/**
		 * The user allowed the bot to send messages.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageBotWriteAccessAllowed(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (WebApp.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.webApp = new WebApp(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageBotWriteAccessAllowed.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageBotWriteAccessAllowed.CONSTRUCTOR);
			if (this.webApp == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.webApp.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageBotWriteAccessAllowed messageBotWriteAccessAllowed = (MessageBotWriteAccessAllowed) o;
			if (!Objects.equals(this.webApp, messageBotWriteAccessAllowed.webApp)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.webApp == null ? 0 : this.webApp.hashCode();
		}
	}

	/**
	 * Data from a Web App has been sent to a bot.
	**/
	public static final class MessageWebAppDataSent extends MessageContent {


		/**
		 * Text of the keyboardButtonTypeWebApp button, which opened the Web App.
		**/
		public String buttonText;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -83674862;

		/**
		 * Data from a Web App has been sent to a bot.
		**/
		public MessageWebAppDataSent() {}

		/**
		 * Data from a Web App has been sent to a bot.
		 *
		 * @param buttonText Text of the keyboardButtonTypeWebApp button, which opened the Web App.
		**/
		public MessageWebAppDataSent(String buttonText) {
			this.buttonText = buttonText;
		}

		/**
		 * Data from a Web App has been sent to a bot.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageWebAppDataSent(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] buttonTextTmp = new byte[input.readInt()];
				input.readFully(buttonTextTmp);
				this.buttonText = new String(buttonTextTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageWebAppDataSent.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageWebAppDataSent.CONSTRUCTOR);
			if (this.buttonText == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] buttonTextTmp = this.buttonText.getBytes(StandardCharsets.UTF_8);
				output.writeInt(buttonTextTmp.length);
				output.write(buttonTextTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageWebAppDataSent messageWebAppDataSent = (MessageWebAppDataSent) o;
			if (this.buttonText != messageWebAppDataSent.buttonText) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.buttonText == null ? 0 : this.buttonText.hashCode();
		}
	}

	/**
	 * Data from a Web App has been received; for bots only.
	**/
	public static final class MessageWebAppDataReceived extends MessageContent {


		/**
		 * Text of the keyboardButtonTypeWebApp button, which opened the Web App.
		**/
		public String buttonText;

		/**
		 * The data.
		**/
		public String data;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -8578539;

		/**
		 * Data from a Web App has been received; for bots only.
		**/
		public MessageWebAppDataReceived() {}

		/**
		 * Data from a Web App has been received; for bots only.
		 *
		 * @param buttonText Text of the keyboardButtonTypeWebApp button, which opened the Web App.
		 * @param data The data.
		**/
		public MessageWebAppDataReceived(String buttonText, String data) {
			this.buttonText = buttonText;
			this.data = data;
		}

		/**
		 * Data from a Web App has been received; for bots only.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageWebAppDataReceived(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] buttonTextTmp = new byte[input.readInt()];
				input.readFully(buttonTextTmp);
				this.buttonText = new String(buttonTextTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] dataTmp = new byte[input.readInt()];
				input.readFully(dataTmp);
				this.data = new String(dataTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageWebAppDataReceived.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageWebAppDataReceived.CONSTRUCTOR);
			if (this.buttonText == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] buttonTextTmp = this.buttonText.getBytes(StandardCharsets.UTF_8);
				output.writeInt(buttonTextTmp.length);
				output.write(buttonTextTmp);
			}
			if (this.data == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] dataTmp = this.data.getBytes(StandardCharsets.UTF_8);
				output.writeInt(dataTmp.length);
				output.write(dataTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageWebAppDataReceived messageWebAppDataReceived = (MessageWebAppDataReceived) o;
			if (this.buttonText != messageWebAppDataReceived.buttonText) {
				return false;
			}
			if (this.data != messageWebAppDataReceived.data) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.buttonText == null ? 0 : this.buttonText.hashCode();
			result = result * 31 + (this.data == null ? 0 : this.data.hashCode());
			return result;
		}
	}

	/**
	 * Telegram Passport data has been sent to a bot.
	**/
	public static final class MessagePassportDataSent extends MessageContent {


		/**
		 * List of Telegram Passport element types sent.
		**/
		public PassportElementType[] types;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1017405171;

		/**
		 * Telegram Passport data has been sent to a bot.
		**/
		public MessagePassportDataSent() {}

		/**
		 * Telegram Passport data has been sent to a bot.
		 *
		 * @param types List of Telegram Passport element types sent.
		**/
		public MessagePassportDataSent(PassportElementType[] types) {
			this.types = types;
		}

		/**
		 * Telegram Passport data has been sent to a bot.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessagePassportDataSent(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.types = new PassportElementType[input.readInt()];
				for (int i = 0; i < this.types.length; i++) {
					switch(input.readInt()) {
						case PassportElementTypePersonalDetails.CONSTRUCTOR: this.types[i] = new PassportElementTypePersonalDetails(input); break;
						case PassportElementTypePassport.CONSTRUCTOR: this.types[i] = new PassportElementTypePassport(input); break;
						case PassportElementTypeDriverLicense.CONSTRUCTOR: this.types[i] = new PassportElementTypeDriverLicense(input); break;
						case PassportElementTypeIdentityCard.CONSTRUCTOR: this.types[i] = new PassportElementTypeIdentityCard(input); break;
						case PassportElementTypeInternalPassport.CONSTRUCTOR: this.types[i] = new PassportElementTypeInternalPassport(input); break;
						case PassportElementTypeAddress.CONSTRUCTOR: this.types[i] = new PassportElementTypeAddress(input); break;
						case PassportElementTypeUtilityBill.CONSTRUCTOR: this.types[i] = new PassportElementTypeUtilityBill(input); break;
						case PassportElementTypeBankStatement.CONSTRUCTOR: this.types[i] = new PassportElementTypeBankStatement(input); break;
						case PassportElementTypeRentalAgreement.CONSTRUCTOR: this.types[i] = new PassportElementTypeRentalAgreement(input); break;
						case PassportElementTypePassportRegistration.CONSTRUCTOR: this.types[i] = new PassportElementTypePassportRegistration(input); break;
						case PassportElementTypeTemporaryRegistration.CONSTRUCTOR: this.types[i] = new PassportElementTypeTemporaryRegistration(input); break;
						case PassportElementTypePhoneNumber.CONSTRUCTOR: this.types[i] = new PassportElementTypePhoneNumber(input); break;
						case PassportElementTypeEmailAddress.CONSTRUCTOR: this.types[i] = new PassportElementTypeEmailAddress(input); break;
						default: {
							throw new UnsupportedOperationException();
						}
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessagePassportDataSent.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessagePassportDataSent.CONSTRUCTOR);
			if (this.types == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.types.length);
				for (int i = 0; i < this.types.length; i++) {
					this.types[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessagePassportDataSent messagePassportDataSent = (MessagePassportDataSent) o;
			if (!Arrays.equals(this.types, messagePassportDataSent.types)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.types);
		}
	}

	/**
	 * Telegram Passport data has been received; for bots only.
	**/
	public static final class MessagePassportDataReceived extends MessageContent {


		/**
		 * List of received Telegram Passport elements.
		**/
		public EncryptedPassportElement[] elements;

		/**
		 * Encrypted data credentials.
		**/
		public EncryptedCredentials credentials;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1367863624;

		/**
		 * Telegram Passport data has been received; for bots only.
		**/
		public MessagePassportDataReceived() {}

		/**
		 * Telegram Passport data has been received; for bots only.
		 *
		 * @param elements List of received Telegram Passport elements.
		 * @param credentials Encrypted data credentials.
		**/
		public MessagePassportDataReceived(EncryptedPassportElement[] elements,
				EncryptedCredentials credentials) {
			this.elements = elements;
			this.credentials = credentials;
		}

		/**
		 * Telegram Passport data has been received; for bots only.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessagePassportDataReceived(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.elements = new EncryptedPassportElement[input.readInt()];
				for (int i = 0; i < this.elements.length; i++) {
					if (EncryptedPassportElement.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.elements[i] = new EncryptedPassportElement(input);
				}
			}
			if (input.readBoolean()) {
				if (EncryptedCredentials.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.credentials = new EncryptedCredentials(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessagePassportDataReceived.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessagePassportDataReceived.CONSTRUCTOR);
			if (this.elements == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.elements.length);
				for (int i = 0; i < this.elements.length; i++) {
					this.elements[i].serialize(output);
				}
			}
			if (this.credentials == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.credentials.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessagePassportDataReceived messagePassportDataReceived = (MessagePassportDataReceived) o;
			if (!Arrays.equals(this.elements, messagePassportDataReceived.elements)) {
				return false;
			}
			if (!Objects.equals(this.credentials, messagePassportDataReceived.credentials)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Arrays.hashCode(this.elements);
			result = result * 31 + (this.credentials == null ? 0 : this.credentials.hashCode());
			return result;
		}
	}

	/**
	 * A user in the chat came within proximity alert range.
	**/
	public static final class MessageProximityAlertTriggered extends MessageContent {


		/**
		 * The identifier of a user or chat that triggered the proximity alert.
		**/
		public MessageSender travelerId;

		/**
		 * The identifier of a user or chat that subscribed for the proximity alert.
		**/
		public MessageSender watcherId;

		/**
		 * The distance between the users.
		**/
		public int distance;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 67761875;

		/**
		 * A user in the chat came within proximity alert range.
		**/
		public MessageProximityAlertTriggered() {}

		/**
		 * A user in the chat came within proximity alert range.
		 *
		 * @param travelerId The identifier of a user or chat that triggered the proximity alert.
		 * @param watcherId The identifier of a user or chat that subscribed for the proximity alert.
		 * @param distance The distance between the users.
		**/
		public MessageProximityAlertTriggered(MessageSender travelerId,
				MessageSender watcherId,
				int distance) {
			this.travelerId = travelerId;
			this.watcherId = watcherId;
			this.distance = distance;
		}

		/**
		 * A user in the chat came within proximity alert range.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageProximityAlertTriggered(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case MessageSenderUser.CONSTRUCTOR: this.travelerId = new MessageSenderUser(input); break;
					case MessageSenderChat.CONSTRUCTOR: this.travelerId = new MessageSenderChat(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case MessageSenderUser.CONSTRUCTOR: this.watcherId = new MessageSenderUser(input); break;
					case MessageSenderChat.CONSTRUCTOR: this.watcherId = new MessageSenderChat(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.distance = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageProximityAlertTriggered.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageProximityAlertTriggered.CONSTRUCTOR);
			if (this.travelerId == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.travelerId.serialize(output);
			}
			if (this.watcherId == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.watcherId.serialize(output);
			}
			output.writeInt(this.distance);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageProximityAlertTriggered messageProximityAlertTriggered = (MessageProximityAlertTriggered) o;
			if (!Objects.equals(this.travelerId, messageProximityAlertTriggered.travelerId)) {
				return false;
			}
			if (!Objects.equals(this.watcherId, messageProximityAlertTriggered.watcherId)) {
				return false;
			}
			if (this.distance != messageProximityAlertTriggered.distance) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.distance);
			result = result * 31 + (this.travelerId == null ? 0 : this.travelerId.hashCode());
			result = result * 31 + (this.watcherId == null ? 0 : this.watcherId.hashCode());
			return result;
		}
	}

	/**
	 * Message content that is not supported in the current TDLib version.
	**/
	public static final class MessageUnsupported extends MessageContent {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1816726139;

		/**
		 * Message content that is not supported in the current TDLib version.
		**/
		public MessageUnsupported() {}

		/**
		 * Message content that is not supported in the current TDLib version.
		 *
		**/

		/**
		 * Message content that is not supported in the current TDLib version.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageUnsupported(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageUnsupported.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageUnsupported.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return MessageUnsupported.CONSTRUCTOR;
		}
	}

	/**
	 * Options to be used when a message content is copied without reference
	 * to the original sender. Service messages and messageInvoice
	 * can&#039;t be copied.
	**/
	public static final class MessageCopyOptions extends Object {


		/**
		 * True, if content of the message needs to be copied without reference to the original sender. Always true if the message is forwarded to a secret chat or is local.
		**/
		public boolean sendCopy;

		/**
		 * True, if media caption of the message copy needs to be replaced. Ignored if sendCopy is false.
		**/
		public boolean replaceCaption;

		/**
		 * New message caption; pass null to copy message without caption. Ignored if replaceCaption is false.
		**/
		public FormattedText newCaption;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1208442937;

		/**
		 * Options to be used when a message content is copied without reference to the original sender. Service messages and messageInvoice can&#039;t be copied.
		**/
		public MessageCopyOptions() {}

		/**
		 * Options to be used when a message content is copied without reference to the original sender. Service messages and messageInvoice can&#039;t be copied.
		 *
		 * @param sendCopy True, if content of the message needs to be copied without reference to the original sender. Always true if the message is forwarded to a secret chat or is local.
		 * @param replaceCaption True, if media caption of the message copy needs to be replaced. Ignored if sendCopy is false.
		 * @param newCaption New message caption; pass null to copy message without caption. Ignored if replaceCaption is false.
		**/
		public MessageCopyOptions(boolean sendCopy,
				boolean replaceCaption,
				FormattedText newCaption) {
			this.sendCopy = sendCopy;
			this.replaceCaption = replaceCaption;
			this.newCaption = newCaption;
		}

		/**
		 * Options to be used when a message content is copied without reference to the original sender. Service messages and messageInvoice can&#039;t be copied.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageCopyOptions(DataInput input) throws IOException {
			this.sendCopy = input.readBoolean();
			this.replaceCaption = input.readBoolean();
			if (input.readBoolean()) {
				if (FormattedText.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.newCaption = new FormattedText(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageCopyOptions.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageCopyOptions.CONSTRUCTOR);
			output.writeBoolean(this.sendCopy);
			output.writeBoolean(this.replaceCaption);
			if (this.newCaption == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.newCaption.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageCopyOptions messageCopyOptions = (MessageCopyOptions) o;
			if (this.sendCopy != messageCopyOptions.sendCopy) {
				return false;
			}
			if (this.replaceCaption != messageCopyOptions.replaceCaption) {
				return false;
			}
			if (!Objects.equals(this.newCaption, messageCopyOptions.newCaption)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.sendCopy);
			result = result * 31 + (this.newCaption == null ? 0 : this.newCaption.hashCode());
			return result;
		}
	}

	/**
	 * The media is hidden until the invoice is paid.
	**/
	public static final class MessageExtendedMediaPreview extends MessageExtendedMedia {


		/**
		 * Media width; 0 if unknown.
		**/
		public int width;

		/**
		 * Media height; 0 if unknown.
		**/
		public int height;

		/**
		 * Media duration; 0 if unknown.
		**/
		public int duration;

		/**
		 * Media minithumbnail; may be null.
		**/
		public Minithumbnail minithumbnail;

		/**
		 * Media caption.
		**/
		public FormattedText caption;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1996727111;

		/**
		 * The media is hidden until the invoice is paid.
		**/
		public MessageExtendedMediaPreview() {}

		/**
		 * The media is hidden until the invoice is paid.
		 *
		 * @param width Media width; 0 if unknown.
		 * @param height Media height; 0 if unknown.
		 * @param duration Media duration; 0 if unknown.
		 * @param minithumbnail Media minithumbnail; may be null.
		 * @param caption Media caption.
		**/
		public MessageExtendedMediaPreview(int width,
				int height,
				int duration,
				Minithumbnail minithumbnail,
				FormattedText caption) {
			this.width = width;
			this.height = height;
			this.duration = duration;
			this.minithumbnail = minithumbnail;
			this.caption = caption;
		}

		/**
		 * The media is hidden until the invoice is paid.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageExtendedMediaPreview(DataInput input) throws IOException {
			this.width = input.readInt();
			this.height = input.readInt();
			this.duration = input.readInt();
			if (input.readBoolean()) {
				if (Minithumbnail.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.minithumbnail = new Minithumbnail(input);
			}
			if (input.readBoolean()) {
				if (FormattedText.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.caption = new FormattedText(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageExtendedMediaPreview.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageExtendedMediaPreview.CONSTRUCTOR);
			output.writeInt(this.width);
			output.writeInt(this.height);
			output.writeInt(this.duration);
			if (this.minithumbnail == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.minithumbnail.serialize(output);
			}
			if (this.caption == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.caption.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageExtendedMediaPreview messageExtendedMediaPreview = (MessageExtendedMediaPreview) o;
			if (this.width != messageExtendedMediaPreview.width) {
				return false;
			}
			if (this.height != messageExtendedMediaPreview.height) {
				return false;
			}
			if (this.duration != messageExtendedMediaPreview.duration) {
				return false;
			}
			if (!Objects.equals(this.minithumbnail, messageExtendedMediaPreview.minithumbnail)) {
				return false;
			}
			if (!Objects.equals(this.caption, messageExtendedMediaPreview.caption)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.width);
			result = result * 31 + (this.minithumbnail == null ? 0 : this.minithumbnail.hashCode());
			result = result * 31 + (this.caption == null ? 0 : this.caption.hashCode());
			return result;
		}
	}

	/**
	 * The media is a photo.
	**/
	public static final class MessageExtendedMediaPhoto extends MessageExtendedMedia {


		/**
		 * The photo.
		**/
		public Photo photo;

		/**
		 * Photo caption.
		**/
		public FormattedText caption;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -963951312;

		/**
		 * The media is a photo.
		**/
		public MessageExtendedMediaPhoto() {}

		/**
		 * The media is a photo.
		 *
		 * @param photo The photo.
		 * @param caption Photo caption.
		**/
		public MessageExtendedMediaPhoto(Photo photo, FormattedText caption) {
			this.photo = photo;
			this.caption = caption;
		}

		/**
		 * The media is a photo.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageExtendedMediaPhoto(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Photo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.photo = new Photo(input);
			}
			if (input.readBoolean()) {
				if (FormattedText.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.caption = new FormattedText(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageExtendedMediaPhoto.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageExtendedMediaPhoto.CONSTRUCTOR);
			if (this.photo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.photo.serialize(output);
			}
			if (this.caption == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.caption.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageExtendedMediaPhoto messageExtendedMediaPhoto = (MessageExtendedMediaPhoto) o;
			if (!Objects.equals(this.photo, messageExtendedMediaPhoto.photo)) {
				return false;
			}
			if (!Objects.equals(this.caption, messageExtendedMediaPhoto.caption)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.photo == null ? 0 : this.photo.hashCode();
			result = result * 31 + (this.caption == null ? 0 : this.caption.hashCode());
			return result;
		}
	}

	/**
	 * The media is a video.
	**/
	public static final class MessageExtendedMediaVideo extends MessageExtendedMedia {


		/**
		 * The video.
		**/
		public Video video;

		/**
		 * Photo caption.
		**/
		public FormattedText caption;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 296533819;

		/**
		 * The media is a video.
		**/
		public MessageExtendedMediaVideo() {}

		/**
		 * The media is a video.
		 *
		 * @param video The video.
		 * @param caption Photo caption.
		**/
		public MessageExtendedMediaVideo(Video video, FormattedText caption) {
			this.video = video;
			this.caption = caption;
		}

		/**
		 * The media is a video.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageExtendedMediaVideo(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Video.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.video = new Video(input);
			}
			if (input.readBoolean()) {
				if (FormattedText.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.caption = new FormattedText(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageExtendedMediaVideo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageExtendedMediaVideo.CONSTRUCTOR);
			if (this.video == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.video.serialize(output);
			}
			if (this.caption == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.caption.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageExtendedMediaVideo messageExtendedMediaVideo = (MessageExtendedMediaVideo) o;
			if (!Objects.equals(this.video, messageExtendedMediaVideo.video)) {
				return false;
			}
			if (!Objects.equals(this.caption, messageExtendedMediaVideo.caption)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.video == null ? 0 : this.video.hashCode();
			result = result * 31 + (this.caption == null ? 0 : this.caption.hashCode());
			return result;
		}
	}

	/**
	 * The media is unsupported.
	**/
	public static final class MessageExtendedMediaUnsupported extends MessageExtendedMedia {


		/**
		 * Media caption.
		**/
		public FormattedText caption;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 337596448;

		/**
		 * The media is unsupported.
		**/
		public MessageExtendedMediaUnsupported() {}

		/**
		 * The media is unsupported.
		 *
		 * @param caption Media caption.
		**/
		public MessageExtendedMediaUnsupported(FormattedText caption) {
			this.caption = caption;
		}

		/**
		 * The media is unsupported.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageExtendedMediaUnsupported(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (FormattedText.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.caption = new FormattedText(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageExtendedMediaUnsupported.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageExtendedMediaUnsupported.CONSTRUCTOR);
			if (this.caption == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.caption.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageExtendedMediaUnsupported messageExtendedMediaUnsupported = (MessageExtendedMediaUnsupported) o;
			if (!Objects.equals(this.caption, messageExtendedMediaUnsupported.caption)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.caption == null ? 0 : this.caption.hashCode();
		}
	}

	/**
	 * The messages was exported from a private chat.
	**/
	public static final class MessageFileTypePrivate extends MessageFileType {


		/**
		 * Name of the other party; may be empty if unrecognized.
		**/
		public String name;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -521908524;

		/**
		 * The messages was exported from a private chat.
		**/
		public MessageFileTypePrivate() {}

		/**
		 * The messages was exported from a private chat.
		 *
		 * @param name Name of the other party; may be empty if unrecognized.
		**/
		public MessageFileTypePrivate(String name) {
			this.name = name;
		}

		/**
		 * The messages was exported from a private chat.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageFileTypePrivate(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] nameTmp = new byte[input.readInt()];
				input.readFully(nameTmp);
				this.name = new String(nameTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageFileTypePrivate.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageFileTypePrivate.CONSTRUCTOR);
			if (this.name == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nameTmp = this.name.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nameTmp.length);
				output.write(nameTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageFileTypePrivate messageFileTypePrivate = (MessageFileTypePrivate) o;
			if (this.name != messageFileTypePrivate.name) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.name == null ? 0 : this.name.hashCode();
		}
	}

	/**
	 * The messages was exported from a group chat.
	**/
	public static final class MessageFileTypeGroup extends MessageFileType {


		/**
		 * Title of the group chat; may be empty if unrecognized.
		**/
		public String title;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -219836568;

		/**
		 * The messages was exported from a group chat.
		**/
		public MessageFileTypeGroup() {}

		/**
		 * The messages was exported from a group chat.
		 *
		 * @param title Title of the group chat; may be empty if unrecognized.
		**/
		public MessageFileTypeGroup(String title) {
			this.title = title;
		}

		/**
		 * The messages was exported from a group chat.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageFileTypeGroup(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageFileTypeGroup.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageFileTypeGroup.CONSTRUCTOR);
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageFileTypeGroup messageFileTypeGroup = (MessageFileTypeGroup) o;
			if (this.title != messageFileTypeGroup.title) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.title == null ? 0 : this.title.hashCode();
		}
	}

	/**
	 * The messages was exported from a chat of unknown type.
	**/
	public static final class MessageFileTypeUnknown extends MessageFileType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1176353458;

		/**
		 * The messages was exported from a chat of unknown type.
		**/
		public MessageFileTypeUnknown() {}

		/**
		 * The messages was exported from a chat of unknown type.
		 *
		**/

		/**
		 * The messages was exported from a chat of unknown type.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageFileTypeUnknown(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageFileTypeUnknown.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageFileTypeUnknown.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return MessageFileTypeUnknown.CONSTRUCTOR;
		}
	}

	/**
	 * Contains information about a forwarded message.
	**/
	public static final class MessageForwardInfo extends Object {


		/**
		 * Origin of a forwarded message.
		**/
		public MessageForwardOrigin origin;

		/**
		 * Point in time (Unix timestamp) when the message was originally sent.
		**/
		public int date;

		/**
		 * The type of a public service announcement for the forwarded message.
		**/
		public String publicServiceAnnouncementType;

		/**
		 * For messages forwarded to the chat with the current user (Saved Messages), to the Replies bot chat, or to the channel&#039;s discussion group, the identifier of the chat from which the message was forwarded last time; 0 if unknown.
		**/
		public long fromChatId;

		/**
		 * For messages forwarded to the chat with the current user (Saved Messages), to the Replies bot chat, or to the channel&#039;s discussion group, the identifier of the original message from which the new message was forwarded last time; 0 if unknown.
		**/
		public long fromMessageId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -327300408;

		/**
		 * Contains information about a forwarded message.
		**/
		public MessageForwardInfo() {}

		/**
		 * Contains information about a forwarded message.
		 *
		 * @param origin Origin of a forwarded message.
		 * @param date Point in time (Unix timestamp) when the message was originally sent.
		 * @param publicServiceAnnouncementType The type of a public service announcement for the forwarded message.
		 * @param fromChatId For messages forwarded to the chat with the current user (Saved Messages), to the Replies bot chat, or to the channel&#039;s discussion group, the identifier of the chat from which the message was forwarded last time; 0 if unknown.
		 * @param fromMessageId For messages forwarded to the chat with the current user (Saved Messages), to the Replies bot chat, or to the channel&#039;s discussion group, the identifier of the original message from which the new message was forwarded last time; 0 if unknown.
		**/
		public MessageForwardInfo(MessageForwardOrigin origin,
				int date,
				String publicServiceAnnouncementType,
				long fromChatId,
				long fromMessageId) {
			this.origin = origin;
			this.date = date;
			this.publicServiceAnnouncementType = publicServiceAnnouncementType;
			this.fromChatId = fromChatId;
			this.fromMessageId = fromMessageId;
		}

		/**
		 * Contains information about a forwarded message.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageForwardInfo(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case MessageForwardOriginUser.CONSTRUCTOR: this.origin = new MessageForwardOriginUser(input); break;
					case MessageForwardOriginChat.CONSTRUCTOR: this.origin = new MessageForwardOriginChat(input); break;
					case MessageForwardOriginHiddenUser.CONSTRUCTOR: this.origin = new MessageForwardOriginHiddenUser(input); break;
					case MessageForwardOriginChannel.CONSTRUCTOR: this.origin = new MessageForwardOriginChannel(input); break;
					case MessageForwardOriginMessageImport.CONSTRUCTOR: this.origin = new MessageForwardOriginMessageImport(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.date = input.readInt();
			if (input.readBoolean()) {
				byte[] publicServiceAnnouncementTypeTmp = new byte[input.readInt()];
				input.readFully(publicServiceAnnouncementTypeTmp);
				this.publicServiceAnnouncementType = new String(publicServiceAnnouncementTypeTmp, StandardCharsets.UTF_8);
			}
			this.fromChatId = input.readLong();
			this.fromMessageId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageForwardInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageForwardInfo.CONSTRUCTOR);
			if (this.origin == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.origin.serialize(output);
			}
			output.writeInt(this.date);
			if (this.publicServiceAnnouncementType == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] publicServiceAnnouncementTypeTmp = this.publicServiceAnnouncementType.getBytes(StandardCharsets.UTF_8);
				output.writeInt(publicServiceAnnouncementTypeTmp.length);
				output.write(publicServiceAnnouncementTypeTmp);
			}
			output.writeLong(this.fromChatId);
			output.writeLong(this.fromMessageId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageForwardInfo messageForwardInfo = (MessageForwardInfo) o;
			if (!Objects.equals(this.origin, messageForwardInfo.origin)) {
				return false;
			}
			if (this.date != messageForwardInfo.date) {
				return false;
			}
			if (this.publicServiceAnnouncementType != messageForwardInfo.publicServiceAnnouncementType) {
				return false;
			}
			if (this.fromChatId != messageForwardInfo.fromChatId) {
				return false;
			}
			if (this.fromMessageId != messageForwardInfo.fromMessageId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.date);
			result = result * 31 + (this.origin == null ? 0 : this.origin.hashCode());
			result = result * 31 + (this.publicServiceAnnouncementType == null ? 0 : this.publicServiceAnnouncementType.hashCode());
			return result;
		}
	}

	/**
	 * The message was originally sent by a known user.
	**/
	public static final class MessageForwardOriginUser extends MessageForwardOrigin {


		/**
		 * Identifier of the user that originally sent the message.
		**/
		public long senderUserId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -355174191;

		/**
		 * The message was originally sent by a known user.
		**/
		public MessageForwardOriginUser() {}

		/**
		 * The message was originally sent by a known user.
		 *
		 * @param senderUserId Identifier of the user that originally sent the message.
		**/
		public MessageForwardOriginUser(long senderUserId) {
			this.senderUserId = senderUserId;
		}

		/**
		 * The message was originally sent by a known user.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageForwardOriginUser(DataInput input) throws IOException {
			this.senderUserId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageForwardOriginUser.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageForwardOriginUser.CONSTRUCTOR);
			output.writeLong(this.senderUserId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageForwardOriginUser messageForwardOriginUser = (MessageForwardOriginUser) o;
			if (this.senderUserId != messageForwardOriginUser.senderUserId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.senderUserId);
		}
	}

	/**
	 * The message was originally sent on behalf of a chat.
	**/
	public static final class MessageForwardOriginChat extends MessageForwardOrigin {


		/**
		 * Identifier of the chat that originally sent the message.
		**/
		public long senderChatId;

		/**
		 * For messages originally sent by an anonymous chat administrator, original message author signature.
		**/
		public String authorSignature;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1526010724;

		/**
		 * The message was originally sent on behalf of a chat.
		**/
		public MessageForwardOriginChat() {}

		/**
		 * The message was originally sent on behalf of a chat.
		 *
		 * @param senderChatId Identifier of the chat that originally sent the message.
		 * @param authorSignature For messages originally sent by an anonymous chat administrator, original message author signature.
		**/
		public MessageForwardOriginChat(long senderChatId, String authorSignature) {
			this.senderChatId = senderChatId;
			this.authorSignature = authorSignature;
		}

		/**
		 * The message was originally sent on behalf of a chat.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageForwardOriginChat(DataInput input) throws IOException {
			this.senderChatId = input.readLong();
			if (input.readBoolean()) {
				byte[] authorSignatureTmp = new byte[input.readInt()];
				input.readFully(authorSignatureTmp);
				this.authorSignature = new String(authorSignatureTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageForwardOriginChat.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageForwardOriginChat.CONSTRUCTOR);
			output.writeLong(this.senderChatId);
			if (this.authorSignature == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] authorSignatureTmp = this.authorSignature.getBytes(StandardCharsets.UTF_8);
				output.writeInt(authorSignatureTmp.length);
				output.write(authorSignatureTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageForwardOriginChat messageForwardOriginChat = (MessageForwardOriginChat) o;
			if (this.senderChatId != messageForwardOriginChat.senderChatId) {
				return false;
			}
			if (this.authorSignature != messageForwardOriginChat.authorSignature) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.senderChatId);
			result = result * 31 + (this.authorSignature == null ? 0 : this.authorSignature.hashCode());
			return result;
		}
	}

	/**
	 * The message was originally sent by a user, which is hidden by their
	 * privacy settings.
	**/
	public static final class MessageForwardOriginHiddenUser extends MessageForwardOrigin {


		/**
		 * Name of the sender.
		**/
		public String senderName;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -271257885;

		/**
		 * The message was originally sent by a user, which is hidden by their privacy settings.
		**/
		public MessageForwardOriginHiddenUser() {}

		/**
		 * The message was originally sent by a user, which is hidden by their privacy settings.
		 *
		 * @param senderName Name of the sender.
		**/
		public MessageForwardOriginHiddenUser(String senderName) {
			this.senderName = senderName;
		}

		/**
		 * The message was originally sent by a user, which is hidden by their privacy settings.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageForwardOriginHiddenUser(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] senderNameTmp = new byte[input.readInt()];
				input.readFully(senderNameTmp);
				this.senderName = new String(senderNameTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageForwardOriginHiddenUser.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageForwardOriginHiddenUser.CONSTRUCTOR);
			if (this.senderName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] senderNameTmp = this.senderName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(senderNameTmp.length);
				output.write(senderNameTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageForwardOriginHiddenUser messageForwardOriginHiddenUser = (MessageForwardOriginHiddenUser) o;
			if (this.senderName != messageForwardOriginHiddenUser.senderName) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.senderName == null ? 0 : this.senderName.hashCode();
		}
	}

	/**
	 * The message was originally a post in a channel.
	**/
	public static final class MessageForwardOriginChannel extends MessageForwardOrigin {


		/**
		 * Identifier of the chat from which the message was originally forwarded.
		**/
		public long chatId;

		/**
		 * Message identifier of the original message.
		**/
		public long messageId;

		/**
		 * Original post author signature.
		**/
		public String authorSignature;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1490730723;

		/**
		 * The message was originally a post in a channel.
		**/
		public MessageForwardOriginChannel() {}

		/**
		 * The message was originally a post in a channel.
		 *
		 * @param chatId Identifier of the chat from which the message was originally forwarded.
		 * @param messageId Message identifier of the original message.
		 * @param authorSignature Original post author signature.
		**/
		public MessageForwardOriginChannel(long chatId, long messageId, String authorSignature) {
			this.chatId = chatId;
			this.messageId = messageId;
			this.authorSignature = authorSignature;
		}

		/**
		 * The message was originally a post in a channel.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageForwardOriginChannel(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
			if (input.readBoolean()) {
				byte[] authorSignatureTmp = new byte[input.readInt()];
				input.readFully(authorSignatureTmp);
				this.authorSignature = new String(authorSignatureTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageForwardOriginChannel.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageForwardOriginChannel.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
			if (this.authorSignature == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] authorSignatureTmp = this.authorSignature.getBytes(StandardCharsets.UTF_8);
				output.writeInt(authorSignatureTmp.length);
				output.write(authorSignatureTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageForwardOriginChannel messageForwardOriginChannel = (MessageForwardOriginChannel) o;
			if (this.chatId != messageForwardOriginChannel.chatId) {
				return false;
			}
			if (this.messageId != messageForwardOriginChannel.messageId) {
				return false;
			}
			if (this.authorSignature != messageForwardOriginChannel.authorSignature) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.authorSignature == null ? 0 : this.authorSignature.hashCode());
			return result;
		}
	}

	/**
	 * The message was imported from an exported message history.
	**/
	public static final class MessageForwardOriginMessageImport extends MessageForwardOrigin {


		/**
		 * Name of the sender.
		**/
		public String senderName;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -739561951;

		/**
		 * The message was imported from an exported message history.
		**/
		public MessageForwardOriginMessageImport() {}

		/**
		 * The message was imported from an exported message history.
		 *
		 * @param senderName Name of the sender.
		**/
		public MessageForwardOriginMessageImport(String senderName) {
			this.senderName = senderName;
		}

		/**
		 * The message was imported from an exported message history.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageForwardOriginMessageImport(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] senderNameTmp = new byte[input.readInt()];
				input.readFully(senderNameTmp);
				this.senderName = new String(senderNameTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageForwardOriginMessageImport.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageForwardOriginMessageImport.CONSTRUCTOR);
			if (this.senderName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] senderNameTmp = this.senderName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(senderNameTmp.length);
				output.write(senderNameTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageForwardOriginMessageImport messageForwardOriginMessageImport = (MessageForwardOriginMessageImport) o;
			if (this.senderName != messageForwardOriginMessageImport.senderName) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.senderName == null ? 0 : this.senderName.hashCode();
		}
	}

	/**
	 * Contains information about interactions with a message.
	**/
	public static final class MessageInteractionInfo extends Object {


		/**
		 * Number of times the message was viewed.
		**/
		public int viewCount;

		/**
		 * Number of times the message was forwarded.
		**/
		public int forwardCount;

		/**
		 * Information about direct or indirect replies to the message; may be null. Currently, available only in channels with a discussion supergroup and discussion supergroups for messages, which are not replies itself.
		**/
		public MessageReplyInfo replyInfo;

		/**
		 * The list of reactions added to the message.
		**/
		public MessageReaction[] reactions;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -574858485;

		/**
		 * Contains information about interactions with a message.
		**/
		public MessageInteractionInfo() {}

		/**
		 * Contains information about interactions with a message.
		 *
		 * @param viewCount Number of times the message was viewed.
		 * @param forwardCount Number of times the message was forwarded.
		 * @param replyInfo Information about direct or indirect replies to the message; may be null. Currently, available only in channels with a discussion supergroup and discussion supergroups for messages, which are not replies itself.
		 * @param reactions The list of reactions added to the message.
		**/
		public MessageInteractionInfo(int viewCount,
				int forwardCount,
				MessageReplyInfo replyInfo,
				MessageReaction[] reactions) {
			this.viewCount = viewCount;
			this.forwardCount = forwardCount;
			this.replyInfo = replyInfo;
			this.reactions = reactions;
		}

		/**
		 * Contains information about interactions with a message.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageInteractionInfo(DataInput input) throws IOException {
			this.viewCount = input.readInt();
			this.forwardCount = input.readInt();
			if (input.readBoolean()) {
				if (MessageReplyInfo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.replyInfo = new MessageReplyInfo(input);
			}
			if (input.readBoolean()) {
				this.reactions = new MessageReaction[input.readInt()];
				for (int i = 0; i < this.reactions.length; i++) {
					if (MessageReaction.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.reactions[i] = new MessageReaction(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageInteractionInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageInteractionInfo.CONSTRUCTOR);
			output.writeInt(this.viewCount);
			output.writeInt(this.forwardCount);
			if (this.replyInfo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.replyInfo.serialize(output);
			}
			if (this.reactions == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.reactions.length);
				for (int i = 0; i < this.reactions.length; i++) {
					this.reactions[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageInteractionInfo messageInteractionInfo = (MessageInteractionInfo) o;
			if (this.viewCount != messageInteractionInfo.viewCount) {
				return false;
			}
			if (this.forwardCount != messageInteractionInfo.forwardCount) {
				return false;
			}
			if (!Objects.equals(this.replyInfo, messageInteractionInfo.replyInfo)) {
				return false;
			}
			if (!Arrays.equals(this.reactions, messageInteractionInfo.reactions)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.viewCount);
			result = result * 31 + (this.replyInfo == null ? 0 : this.replyInfo.hashCode());
			result = result * 31 + (Arrays.hashCode(this.reactions));
			return result;
		}
	}

	/**
	 * Contains an HTTPS link to a message in a supergroup or channel, or a
	 * forum topic.
	**/
	public static final class MessageLink extends Object {


		/**
		 * The link.
		**/
		public String link;

		/**
		 * True, if the link will work for non-members of the chat.
		**/
		public boolean isPublic;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1354089818;

		/**
		 * Contains an HTTPS link to a message in a supergroup or channel, or a forum topic.
		**/
		public MessageLink() {}

		/**
		 * Contains an HTTPS link to a message in a supergroup or channel, or a forum topic.
		 *
		 * @param link The link.
		 * @param isPublic True, if the link will work for non-members of the chat.
		**/
		public MessageLink(String link, boolean isPublic) {
			this.link = link;
			this.isPublic = isPublic;
		}

		/**
		 * Contains an HTTPS link to a message in a supergroup or channel, or a forum topic.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageLink(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] linkTmp = new byte[input.readInt()];
				input.readFully(linkTmp);
				this.link = new String(linkTmp, StandardCharsets.UTF_8);
			}
			this.isPublic = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageLink.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageLink.CONSTRUCTOR);
			if (this.link == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] linkTmp = this.link.getBytes(StandardCharsets.UTF_8);
				output.writeInt(linkTmp.length);
				output.write(linkTmp);
			}
			output.writeBoolean(this.isPublic);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageLink messageLink = (MessageLink) o;
			if (this.link != messageLink.link) {
				return false;
			}
			if (this.isPublic != messageLink.isPublic) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isPublic);
			result = result * 31 + (this.link == null ? 0 : this.link.hashCode());
			return result;
		}
	}

	/**
	 * Contains information about a link to a message or a forum topic in a
	 * chat.
	**/
	public static final class MessageLinkInfo extends Object {


		/**
		 * True, if the link is a public link for a message or a forum topic in a chat.
		**/
		public boolean isPublic;

		/**
		 * If found, identifier of the chat to which the link points, 0 otherwise.
		**/
		public long chatId;

		/**
		 * If found, identifier of the message thread in which to open the message, or a forum topic to open if the message is missing.
		**/
		public long messageThreadId;

		/**
		 * If found, the linked message; may be null.
		**/
		public Message message;

		/**
		 * Timestamp from which the video/audio/video note/voice note playing must start, in seconds; 0 if not specified. The media can be in the message content or in its web page preview.
		**/
		public int mediaTimestamp;

		/**
		 * True, if the whole media album to which the message belongs is linked.
		**/
		public boolean forAlbum;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 731315024;

		/**
		 * Contains information about a link to a message or a forum topic in a chat.
		**/
		public MessageLinkInfo() {}

		/**
		 * Contains information about a link to a message or a forum topic in a chat.
		 *
		 * @param isPublic True, if the link is a public link for a message or a forum topic in a chat.
		 * @param chatId If found, identifier of the chat to which the link points, 0 otherwise.
		 * @param messageThreadId If found, identifier of the message thread in which to open the message, or a forum topic to open if the message is missing.
		 * @param message If found, the linked message; may be null.
		 * @param mediaTimestamp Timestamp from which the video/audio/video note/voice note playing must start, in seconds; 0 if not specified. The media can be in the message content or in its web page preview.
		 * @param forAlbum True, if the whole media album to which the message belongs is linked.
		**/
		public MessageLinkInfo(boolean isPublic,
				long chatId,
				long messageThreadId,
				Message message,
				int mediaTimestamp,
				boolean forAlbum) {
			this.isPublic = isPublic;
			this.chatId = chatId;
			this.messageThreadId = messageThreadId;
			this.message = message;
			this.mediaTimestamp = mediaTimestamp;
			this.forAlbum = forAlbum;
		}

		/**
		 * Contains information about a link to a message or a forum topic in a chat.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageLinkInfo(DataInput input) throws IOException {
			this.isPublic = input.readBoolean();
			this.chatId = input.readLong();
			this.messageThreadId = input.readLong();
			if (input.readBoolean()) {
				if (Message.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.message = new Message(input);
			}
			this.mediaTimestamp = input.readInt();
			this.forAlbum = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageLinkInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageLinkInfo.CONSTRUCTOR);
			output.writeBoolean(this.isPublic);
			output.writeLong(this.chatId);
			output.writeLong(this.messageThreadId);
			if (this.message == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.message.serialize(output);
			}
			output.writeInt(this.mediaTimestamp);
			output.writeBoolean(this.forAlbum);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageLinkInfo messageLinkInfo = (MessageLinkInfo) o;
			if (this.isPublic != messageLinkInfo.isPublic) {
				return false;
			}
			if (this.chatId != messageLinkInfo.chatId) {
				return false;
			}
			if (this.messageThreadId != messageLinkInfo.messageThreadId) {
				return false;
			}
			if (!Objects.equals(this.message, messageLinkInfo.message)) {
				return false;
			}
			if (this.mediaTimestamp != messageLinkInfo.mediaTimestamp) {
				return false;
			}
			if (this.forAlbum != messageLinkInfo.forAlbum) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isPublic);
			result = result * 31 + (this.message == null ? 0 : this.message.hashCode());
			return result;
		}
	}

	/**
	 * Contains information about a message in a specific position.
	**/
	public static final class MessagePosition extends Object {


		/**
		 * 0-based message position in the full list of suitable messages.
		**/
		public int position;

		/**
		 * Message identifier.
		**/
		public long messageId;

		/**
		 * Point in time (Unix timestamp) when the message was sent.
		**/
		public int date;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1292189935;

		/**
		 * Contains information about a message in a specific position.
		**/
		public MessagePosition() {}

		/**
		 * Contains information about a message in a specific position.
		 *
		 * @param position 0-based message position in the full list of suitable messages.
		 * @param messageId Message identifier.
		 * @param date Point in time (Unix timestamp) when the message was sent.
		**/
		public MessagePosition(int position, long messageId, int date) {
			this.position = position;
			this.messageId = messageId;
			this.date = date;
		}

		/**
		 * Contains information about a message in a specific position.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessagePosition(DataInput input) throws IOException {
			this.position = input.readInt();
			this.messageId = input.readLong();
			this.date = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessagePosition.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessagePosition.CONSTRUCTOR);
			output.writeInt(this.position);
			output.writeLong(this.messageId);
			output.writeInt(this.date);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessagePosition messagePosition = (MessagePosition) o;
			if (this.position != messagePosition.position) {
				return false;
			}
			if (this.messageId != messagePosition.messageId) {
				return false;
			}
			if (this.date != messagePosition.date) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.position);
			return result;
		}
	}

	/**
	 * Contains a list of message positions.
	**/
	public static final class MessagePositions extends Object {


		/**
		 * Total number of messages found.
		**/
		public int totalCount;

		/**
		 * List of message positions.
		**/
		public MessagePosition[] positions;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1930466649;

		/**
		 * Contains a list of message positions.
		**/
		public MessagePositions() {}

		/**
		 * Contains a list of message positions.
		 *
		 * @param totalCount Total number of messages found.
		 * @param positions List of message positions.
		**/
		public MessagePositions(int totalCount, MessagePosition[] positions) {
			this.totalCount = totalCount;
			this.positions = positions;
		}

		/**
		 * Contains a list of message positions.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessagePositions(DataInput input) throws IOException {
			this.totalCount = input.readInt();
			if (input.readBoolean()) {
				this.positions = new MessagePosition[input.readInt()];
				for (int i = 0; i < this.positions.length; i++) {
					if (MessagePosition.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.positions[i] = new MessagePosition(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessagePositions.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessagePositions.CONSTRUCTOR);
			output.writeInt(this.totalCount);
			if (this.positions == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.positions.length);
				for (int i = 0; i < this.positions.length; i++) {
					this.positions[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessagePositions messagePositions = (MessagePositions) o;
			if (this.totalCount != messagePositions.totalCount) {
				return false;
			}
			if (!Arrays.equals(this.positions, messagePositions.positions)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.totalCount);
			result = result * 31 + (Arrays.hashCode(this.positions));
			return result;
		}
	}

	/**
	 * Contains information about a reaction to a message.
	**/
	public static final class MessageReaction extends Object {


		/**
		 * Type of the reaction.
		**/
		public ReactionType type;

		/**
		 * Number of times the reaction was added.
		**/
		public int totalCount;

		/**
		 * True, if the reaction is chosen by the current user.
		**/
		public boolean isChosen;

		/**
		 * Identifiers of at most 3 recent message senders, added the reaction; available in private, basic group and supergroup chats.
		**/
		public MessageSender[] recentSenderIds;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 583566666;

		/**
		 * Contains information about a reaction to a message.
		**/
		public MessageReaction() {}

		/**
		 * Contains information about a reaction to a message.
		 *
		 * @param type Type of the reaction.
		 * @param totalCount Number of times the reaction was added.
		 * @param isChosen True, if the reaction is chosen by the current user.
		 * @param recentSenderIds Identifiers of at most 3 recent message senders, added the reaction; available in private, basic group and supergroup chats.
		**/
		public MessageReaction(ReactionType type,
				int totalCount,
				boolean isChosen,
				MessageSender[] recentSenderIds) {
			this.type = type;
			this.totalCount = totalCount;
			this.isChosen = isChosen;
			this.recentSenderIds = recentSenderIds;
		}

		/**
		 * Contains information about a reaction to a message.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageReaction(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ReactionTypeEmoji.CONSTRUCTOR: this.type = new ReactionTypeEmoji(input); break;
					case ReactionTypeCustomEmoji.CONSTRUCTOR: this.type = new ReactionTypeCustomEmoji(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.totalCount = input.readInt();
			this.isChosen = input.readBoolean();
			if (input.readBoolean()) {
				this.recentSenderIds = new MessageSender[input.readInt()];
				for (int i = 0; i < this.recentSenderIds.length; i++) {
					switch(input.readInt()) {
						case MessageSenderUser.CONSTRUCTOR: this.recentSenderIds[i] = new MessageSenderUser(input); break;
						case MessageSenderChat.CONSTRUCTOR: this.recentSenderIds[i] = new MessageSenderChat(input); break;
						default: {
							throw new UnsupportedOperationException();
						}
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageReaction.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageReaction.CONSTRUCTOR);
			if (this.type == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.type.serialize(output);
			}
			output.writeInt(this.totalCount);
			output.writeBoolean(this.isChosen);
			if (this.recentSenderIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.recentSenderIds.length);
				for (int i = 0; i < this.recentSenderIds.length; i++) {
					this.recentSenderIds[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageReaction messageReaction = (MessageReaction) o;
			if (!Objects.equals(this.type, messageReaction.type)) {
				return false;
			}
			if (this.totalCount != messageReaction.totalCount) {
				return false;
			}
			if (this.isChosen != messageReaction.isChosen) {
				return false;
			}
			if (!Arrays.equals(this.recentSenderIds, messageReaction.recentSenderIds)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.totalCount);
			result = result * 31 + (this.type == null ? 0 : this.type.hashCode());
			result = result * 31 + (Arrays.hashCode(this.recentSenderIds));
			return result;
		}
	}

	/**
	 * Contains information about replies to a message.
	**/
	public static final class MessageReplyInfo extends Object {


		/**
		 * Number of times the message was directly or indirectly replied.
		**/
		public int replyCount;

		/**
		 * Identifiers of at most 3 recent repliers to the message; available in channels with a discussion supergroup. The users and chats are expected to be inaccessible: only their photo and name will be available.
		**/
		public MessageSender[] recentReplierIds;

		/**
		 * Identifier of the last read incoming reply to the message.
		**/
		public long lastReadInboxMessageId;

		/**
		 * Identifier of the last read outgoing reply to the message.
		**/
		public long lastReadOutboxMessageId;

		/**
		 * Identifier of the last reply to the message.
		**/
		public long lastMessageId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2093702263;

		/**
		 * Contains information about replies to a message.
		**/
		public MessageReplyInfo() {}

		/**
		 * Contains information about replies to a message.
		 *
		 * @param replyCount Number of times the message was directly or indirectly replied.
		 * @param recentReplierIds Identifiers of at most 3 recent repliers to the message; available in channels with a discussion supergroup. The users and chats are expected to be inaccessible: only their photo and name will be available.
		 * @param lastReadInboxMessageId Identifier of the last read incoming reply to the message.
		 * @param lastReadOutboxMessageId Identifier of the last read outgoing reply to the message.
		 * @param lastMessageId Identifier of the last reply to the message.
		**/
		public MessageReplyInfo(int replyCount,
				MessageSender[] recentReplierIds,
				long lastReadInboxMessageId,
				long lastReadOutboxMessageId,
				long lastMessageId) {
			this.replyCount = replyCount;
			this.recentReplierIds = recentReplierIds;
			this.lastReadInboxMessageId = lastReadInboxMessageId;
			this.lastReadOutboxMessageId = lastReadOutboxMessageId;
			this.lastMessageId = lastMessageId;
		}

		/**
		 * Contains information about replies to a message.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageReplyInfo(DataInput input) throws IOException {
			this.replyCount = input.readInt();
			if (input.readBoolean()) {
				this.recentReplierIds = new MessageSender[input.readInt()];
				for (int i = 0; i < this.recentReplierIds.length; i++) {
					switch(input.readInt()) {
						case MessageSenderUser.CONSTRUCTOR: this.recentReplierIds[i] = new MessageSenderUser(input); break;
						case MessageSenderChat.CONSTRUCTOR: this.recentReplierIds[i] = new MessageSenderChat(input); break;
						default: {
							throw new UnsupportedOperationException();
						}
					}
				}
			}
			this.lastReadInboxMessageId = input.readLong();
			this.lastReadOutboxMessageId = input.readLong();
			this.lastMessageId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageReplyInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageReplyInfo.CONSTRUCTOR);
			output.writeInt(this.replyCount);
			if (this.recentReplierIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.recentReplierIds.length);
				for (int i = 0; i < this.recentReplierIds.length; i++) {
					this.recentReplierIds[i].serialize(output);
				}
			}
			output.writeLong(this.lastReadInboxMessageId);
			output.writeLong(this.lastReadOutboxMessageId);
			output.writeLong(this.lastMessageId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageReplyInfo messageReplyInfo = (MessageReplyInfo) o;
			if (this.replyCount != messageReplyInfo.replyCount) {
				return false;
			}
			if (!Arrays.equals(this.recentReplierIds, messageReplyInfo.recentReplierIds)) {
				return false;
			}
			if (this.lastReadInboxMessageId != messageReplyInfo.lastReadInboxMessageId) {
				return false;
			}
			if (this.lastReadOutboxMessageId != messageReplyInfo.lastReadOutboxMessageId) {
				return false;
			}
			if (this.lastMessageId != messageReplyInfo.lastMessageId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.replyCount);
			result = result * 31 + (Arrays.hashCode(this.recentReplierIds));
			return result;
		}
	}

	/**
	 * The message will be sent at the specified date.
	**/
	public static final class MessageSchedulingStateSendAtDate extends MessageSchedulingState {


		/**
		 * Date the message will be sent. The date must be within 367 days in the future.
		**/
		public int sendDate;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1485570073;

		/**
		 * The message will be sent at the specified date.
		**/
		public MessageSchedulingStateSendAtDate() {}

		/**
		 * The message will be sent at the specified date.
		 *
		 * @param sendDate Date the message will be sent. The date must be within 367 days in the future.
		**/
		public MessageSchedulingStateSendAtDate(int sendDate) {
			this.sendDate = sendDate;
		}

		/**
		 * The message will be sent at the specified date.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageSchedulingStateSendAtDate(DataInput input) throws IOException {
			this.sendDate = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageSchedulingStateSendAtDate.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageSchedulingStateSendAtDate.CONSTRUCTOR);
			output.writeInt(this.sendDate);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageSchedulingStateSendAtDate messageSchedulingStateSendAtDate = (MessageSchedulingStateSendAtDate) o;
			if (this.sendDate != messageSchedulingStateSendAtDate.sendDate) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.sendDate);
		}
	}

	/**
	 * The message will be sent when the peer will be online. Applicable to
	 * private chats only and when the exact online status of the peer is
	 * known.
	**/
	public static final class MessageSchedulingStateSendWhenOnline extends MessageSchedulingState {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2092947464;

		/**
		 * The message will be sent when the peer will be online. Applicable to private chats only and when the exact online status of the peer is known.
		**/
		public MessageSchedulingStateSendWhenOnline() {}

		/**
		 * The message will be sent when the peer will be online. Applicable to private chats only and when the exact online status of the peer is known.
		 *
		**/

		/**
		 * The message will be sent when the peer will be online. Applicable to private chats only and when the exact online status of the peer is known.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageSchedulingStateSendWhenOnline(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageSchedulingStateSendWhenOnline.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageSchedulingStateSendWhenOnline.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return MessageSchedulingStateSendWhenOnline.CONSTRUCTOR;
		}
	}

	/**
	 * Options to be used when a message is sent.
	**/
	public static final class MessageSendOptions extends Object {


		/**
		 * Pass true to disable notification for the message.
		**/
		public boolean disableNotification;

		/**
		 * Pass true if the message is sent from the background.
		**/
		public boolean fromBackground;

		/**
		 * Pass true if the content of the message must be protected from forwarding and saving; for bots only.
		**/
		public boolean protectContent;

		/**
		 * Pass true if the user explicitly chosen a sticker or a custom emoji from an installed sticker set; applicable only to sendMessage and sendMessageAlbum.
		**/
		public boolean updateOrderOfInstalledStickerSets;

		/**
		 * Message scheduling state; pass null to send message immediately. Messages sent to a secret chat, live location messages and self-destructing messages can&#039;t be scheduled.
		**/
		public MessageSchedulingState schedulingState;

		/**
		 * Non-persistent identifier, which will be returned back in messageSendingStatePending object and can be used to match sent messages and corresponding updateNewMessage updates.
		**/
		public int sendingId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 32902046;

		/**
		 * Options to be used when a message is sent.
		**/
		public MessageSendOptions() {}

		/**
		 * Options to be used when a message is sent.
		 *
		 * @param disableNotification Pass true to disable notification for the message.
		 * @param fromBackground Pass true if the message is sent from the background.
		 * @param protectContent Pass true if the content of the message must be protected from forwarding and saving; for bots only.
		 * @param updateOrderOfInstalledStickerSets Pass true if the user explicitly chosen a sticker or a custom emoji from an installed sticker set; applicable only to sendMessage and sendMessageAlbum.
		 * @param schedulingState Message scheduling state; pass null to send message immediately. Messages sent to a secret chat, live location messages and self-destructing messages can&#039;t be scheduled.
		 * @param sendingId Non-persistent identifier, which will be returned back in messageSendingStatePending object and can be used to match sent messages and corresponding updateNewMessage updates.
		**/
		public MessageSendOptions(boolean disableNotification,
				boolean fromBackground,
				boolean protectContent,
				boolean updateOrderOfInstalledStickerSets,
				MessageSchedulingState schedulingState,
				int sendingId) {
			this.disableNotification = disableNotification;
			this.fromBackground = fromBackground;
			this.protectContent = protectContent;
			this.updateOrderOfInstalledStickerSets = updateOrderOfInstalledStickerSets;
			this.schedulingState = schedulingState;
			this.sendingId = sendingId;
		}

		/**
		 * Options to be used when a message is sent.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageSendOptions(DataInput input) throws IOException {
			this.disableNotification = input.readBoolean();
			this.fromBackground = input.readBoolean();
			this.protectContent = input.readBoolean();
			this.updateOrderOfInstalledStickerSets = input.readBoolean();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case MessageSchedulingStateSendAtDate.CONSTRUCTOR: this.schedulingState = new MessageSchedulingStateSendAtDate(input); break;
					case MessageSchedulingStateSendWhenOnline.CONSTRUCTOR: this.schedulingState = new MessageSchedulingStateSendWhenOnline(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.sendingId = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageSendOptions.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageSendOptions.CONSTRUCTOR);
			output.writeBoolean(this.disableNotification);
			output.writeBoolean(this.fromBackground);
			output.writeBoolean(this.protectContent);
			output.writeBoolean(this.updateOrderOfInstalledStickerSets);
			if (this.schedulingState == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.schedulingState.serialize(output);
			}
			output.writeInt(this.sendingId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageSendOptions messageSendOptions = (MessageSendOptions) o;
			if (this.disableNotification != messageSendOptions.disableNotification) {
				return false;
			}
			if (this.fromBackground != messageSendOptions.fromBackground) {
				return false;
			}
			if (this.protectContent != messageSendOptions.protectContent) {
				return false;
			}
			if (this.updateOrderOfInstalledStickerSets != messageSendOptions.updateOrderOfInstalledStickerSets) {
				return false;
			}
			if (!Objects.equals(this.schedulingState, messageSendOptions.schedulingState)) {
				return false;
			}
			if (this.sendingId != messageSendOptions.sendingId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.disableNotification);
			result = result * 31 + (this.schedulingState == null ? 0 : this.schedulingState.hashCode());
			return result;
		}
	}

	/**
	 * The message was sent by a known user.
	**/
	public static final class MessageSenderUser extends MessageSender {


		/**
		 * Identifier of the user that sent the message.
		**/
		public long userId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -336109341;

		/**
		 * The message was sent by a known user.
		**/
		public MessageSenderUser() {}

		/**
		 * The message was sent by a known user.
		 *
		 * @param userId Identifier of the user that sent the message.
		**/
		public MessageSenderUser(long userId) {
			this.userId = userId;
		}

		/**
		 * The message was sent by a known user.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageSenderUser(DataInput input) throws IOException {
			this.userId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageSenderUser.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageSenderUser.CONSTRUCTOR);
			output.writeLong(this.userId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageSenderUser messageSenderUser = (MessageSenderUser) o;
			if (this.userId != messageSenderUser.userId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.userId);
		}
	}

	/**
	 * The message was sent on behalf of a chat.
	**/
	public static final class MessageSenderChat extends MessageSender {


		/**
		 * Identifier of the chat that sent the message.
		**/
		public long chatId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -239660751;

		/**
		 * The message was sent on behalf of a chat.
		**/
		public MessageSenderChat() {}

		/**
		 * The message was sent on behalf of a chat.
		 *
		 * @param chatId Identifier of the chat that sent the message.
		**/
		public MessageSenderChat(long chatId) {
			this.chatId = chatId;
		}

		/**
		 * The message was sent on behalf of a chat.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageSenderChat(DataInput input) throws IOException {
			this.chatId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageSenderChat.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageSenderChat.CONSTRUCTOR);
			output.writeLong(this.chatId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageSenderChat messageSenderChat = (MessageSenderChat) o;
			if (this.chatId != messageSenderChat.chatId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.chatId);
		}
	}

	/**
	 * Represents a list of message senders.
	**/
	public static final class MessageSenders extends Object {


		/**
		 * Approximate total number of messages senders found.
		**/
		public int totalCount;

		/**
		 * List of message senders.
		**/
		public MessageSender[] senders;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -690158467;

		/**
		 * Represents a list of message senders.
		**/
		public MessageSenders() {}

		/**
		 * Represents a list of message senders.
		 *
		 * @param totalCount Approximate total number of messages senders found.
		 * @param senders List of message senders.
		**/
		public MessageSenders(int totalCount, MessageSender[] senders) {
			this.totalCount = totalCount;
			this.senders = senders;
		}

		/**
		 * Represents a list of message senders.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageSenders(DataInput input) throws IOException {
			this.totalCount = input.readInt();
			if (input.readBoolean()) {
				this.senders = new MessageSender[input.readInt()];
				for (int i = 0; i < this.senders.length; i++) {
					switch(input.readInt()) {
						case MessageSenderUser.CONSTRUCTOR: this.senders[i] = new MessageSenderUser(input); break;
						case MessageSenderChat.CONSTRUCTOR: this.senders[i] = new MessageSenderChat(input); break;
						default: {
							throw new UnsupportedOperationException();
						}
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageSenders.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageSenders.CONSTRUCTOR);
			output.writeInt(this.totalCount);
			if (this.senders == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.senders.length);
				for (int i = 0; i < this.senders.length; i++) {
					this.senders[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageSenders messageSenders = (MessageSenders) o;
			if (this.totalCount != messageSenders.totalCount) {
				return false;
			}
			if (!Arrays.equals(this.senders, messageSenders.senders)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.totalCount);
			result = result * 31 + (Arrays.hashCode(this.senders));
			return result;
		}
	}

	/**
	 * The message is being sent now, but has not yet been delivered to the
	 * server.
	**/
	public static final class MessageSendingStatePending extends MessageSendingState {


		/**
		 * Non-persistent message sending identifier, specified by the application.
		**/
		public int sendingId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -215260236;

		/**
		 * The message is being sent now, but has not yet been delivered to the server.
		**/
		public MessageSendingStatePending() {}

		/**
		 * The message is being sent now, but has not yet been delivered to the server.
		 *
		 * @param sendingId Non-persistent message sending identifier, specified by the application.
		**/
		public MessageSendingStatePending(int sendingId) {
			this.sendingId = sendingId;
		}

		/**
		 * The message is being sent now, but has not yet been delivered to the server.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageSendingStatePending(DataInput input) throws IOException {
			this.sendingId = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageSendingStatePending.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageSendingStatePending.CONSTRUCTOR);
			output.writeInt(this.sendingId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageSendingStatePending messageSendingStatePending = (MessageSendingStatePending) o;
			if (this.sendingId != messageSendingStatePending.sendingId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.sendingId);
		}
	}

	/**
	 * The message failed to be sent.
	**/
	public static final class MessageSendingStateFailed extends MessageSendingState {


		/**
		 * An error code; 0 if unknown.
		**/
		public int errorCode;

		/**
		 * Error message.
		**/
		public String errorMessage;

		/**
		 * True, if the message can be re-sent.
		**/
		public boolean canRetry;

		/**
		 * True, if the message can be re-sent only on behalf of a different sender.
		**/
		public boolean needAnotherSender;

		/**
		 * Time left before the message can be re-sent, in seconds. No update is sent when this field changes.
		**/
		public double retryAfter;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1741887228;

		/**
		 * The message failed to be sent.
		**/
		public MessageSendingStateFailed() {}

		/**
		 * The message failed to be sent.
		 *
		 * @param errorCode An error code; 0 if unknown.
		 * @param errorMessage Error message.
		 * @param canRetry True, if the message can be re-sent.
		 * @param needAnotherSender True, if the message can be re-sent only on behalf of a different sender.
		 * @param retryAfter Time left before the message can be re-sent, in seconds. No update is sent when this field changes.
		**/
		public MessageSendingStateFailed(int errorCode,
				String errorMessage,
				boolean canRetry,
				boolean needAnotherSender,
				double retryAfter) {
			this.errorCode = errorCode;
			this.errorMessage = errorMessage;
			this.canRetry = canRetry;
			this.needAnotherSender = needAnotherSender;
			this.retryAfter = retryAfter;
		}

		/**
		 * The message failed to be sent.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageSendingStateFailed(DataInput input) throws IOException {
			this.errorCode = input.readInt();
			if (input.readBoolean()) {
				byte[] errorMessageTmp = new byte[input.readInt()];
				input.readFully(errorMessageTmp);
				this.errorMessage = new String(errorMessageTmp, StandardCharsets.UTF_8);
			}
			this.canRetry = input.readBoolean();
			this.needAnotherSender = input.readBoolean();
			this.retryAfter = input.readDouble();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageSendingStateFailed.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageSendingStateFailed.CONSTRUCTOR);
			output.writeInt(this.errorCode);
			if (this.errorMessage == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] errorMessageTmp = this.errorMessage.getBytes(StandardCharsets.UTF_8);
				output.writeInt(errorMessageTmp.length);
				output.write(errorMessageTmp);
			}
			output.writeBoolean(this.canRetry);
			output.writeBoolean(this.needAnotherSender);
			output.writeDouble(this.retryAfter);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageSendingStateFailed messageSendingStateFailed = (MessageSendingStateFailed) o;
			if (this.errorCode != messageSendingStateFailed.errorCode) {
				return false;
			}
			if (this.errorMessage != messageSendingStateFailed.errorMessage) {
				return false;
			}
			if (this.canRetry != messageSendingStateFailed.canRetry) {
				return false;
			}
			if (this.needAnotherSender != messageSendingStateFailed.needAnotherSender) {
				return false;
			}
			if (this.retryAfter != messageSendingStateFailed.retryAfter) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.errorCode);
			result = result * 31 + (this.errorMessage == null ? 0 : this.errorMessage.hashCode());
			return result;
		}
	}

	/**
	 * The message is from a chat history.
	**/
	public static final class MessageSourceChatHistory extends MessageSource {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1090386116;

		/**
		 * The message is from a chat history.
		**/
		public MessageSourceChatHistory() {}

		/**
		 * The message is from a chat history.
		 *
		**/

		/**
		 * The message is from a chat history.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageSourceChatHistory(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageSourceChatHistory.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageSourceChatHistory.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return MessageSourceChatHistory.CONSTRUCTOR;
		}
	}

	/**
	 * The message is from a message thread history.
	**/
	public static final class MessageSourceMessageThreadHistory extends MessageSource {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 290427142;

		/**
		 * The message is from a message thread history.
		**/
		public MessageSourceMessageThreadHistory() {}

		/**
		 * The message is from a message thread history.
		 *
		**/

		/**
		 * The message is from a message thread history.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageSourceMessageThreadHistory(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageSourceMessageThreadHistory.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageSourceMessageThreadHistory.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return MessageSourceMessageThreadHistory.CONSTRUCTOR;
		}
	}

	/**
	 * The message is from a forum topic history.
	**/
	public static final class MessageSourceForumTopicHistory extends MessageSource {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1518064457;

		/**
		 * The message is from a forum topic history.
		**/
		public MessageSourceForumTopicHistory() {}

		/**
		 * The message is from a forum topic history.
		 *
		**/

		/**
		 * The message is from a forum topic history.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageSourceForumTopicHistory(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageSourceForumTopicHistory.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageSourceForumTopicHistory.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return MessageSourceForumTopicHistory.CONSTRUCTOR;
		}
	}

	/**
	 * The message is from chat, message thread or forum topic history
	 * preview.
	**/
	public static final class MessageSourceHistoryPreview extends MessageSource {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1024254993;

		/**
		 * The message is from chat, message thread or forum topic history preview.
		**/
		public MessageSourceHistoryPreview() {}

		/**
		 * The message is from chat, message thread or forum topic history preview.
		 *
		**/

		/**
		 * The message is from chat, message thread or forum topic history preview.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageSourceHistoryPreview(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageSourceHistoryPreview.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageSourceHistoryPreview.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return MessageSourceHistoryPreview.CONSTRUCTOR;
		}
	}

	/**
	 * The message is from a chat list or a forum topic list.
	**/
	public static final class MessageSourceChatList extends MessageSource {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2047406102;

		/**
		 * The message is from a chat list or a forum topic list.
		**/
		public MessageSourceChatList() {}

		/**
		 * The message is from a chat list or a forum topic list.
		 *
		**/

		/**
		 * The message is from a chat list or a forum topic list.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageSourceChatList(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageSourceChatList.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageSourceChatList.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return MessageSourceChatList.CONSTRUCTOR;
		}
	}

	/**
	 * The message is from search results, including file downloads, local
	 * file list, outgoing document messages, calendar.
	**/
	public static final class MessageSourceSearch extends MessageSource {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1921333105;

		/**
		 * The message is from search results, including file downloads, local file list, outgoing document messages, calendar.
		**/
		public MessageSourceSearch() {}

		/**
		 * The message is from search results, including file downloads, local file list, outgoing document messages, calendar.
		 *
		**/

		/**
		 * The message is from search results, including file downloads, local file list, outgoing document messages, calendar.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageSourceSearch(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageSourceSearch.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageSourceSearch.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return MessageSourceSearch.CONSTRUCTOR;
		}
	}

	/**
	 * The message is from a chat event log.
	**/
	public static final class MessageSourceChatEventLog extends MessageSource {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1028777540;

		/**
		 * The message is from a chat event log.
		**/
		public MessageSourceChatEventLog() {}

		/**
		 * The message is from a chat event log.
		 *
		**/

		/**
		 * The message is from a chat event log.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageSourceChatEventLog(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageSourceChatEventLog.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageSourceChatEventLog.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return MessageSourceChatEventLog.CONSTRUCTOR;
		}
	}

	/**
	 * The message is from a notification.
	**/
	public static final class MessageSourceNotification extends MessageSource {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1046406163;

		/**
		 * The message is from a notification.
		**/
		public MessageSourceNotification() {}

		/**
		 * The message is from a notification.
		 *
		**/

		/**
		 * The message is from a notification.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageSourceNotification(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageSourceNotification.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageSourceNotification.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return MessageSourceNotification.CONSTRUCTOR;
		}
	}

	/**
	 * The message is from some other source.
	**/
	public static final class MessageSourceOther extends MessageSource {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 901818114;

		/**
		 * The message is from some other source.
		**/
		public MessageSourceOther() {}

		/**
		 * The message is from some other source.
		 *
		**/

		/**
		 * The message is from some other source.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageSourceOther(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageSourceOther.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageSourceOther.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return MessageSourceOther.CONSTRUCTOR;
		}
	}

	/**
	 * A detailed statistics about a message.
	**/
	public static final class MessageStatistics extends Object {


		/**
		 * A graph containing number of message views and shares.
		**/
		public StatisticalGraph messageInteractionGraph;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1011383888;

		/**
		 * A detailed statistics about a message.
		**/
		public MessageStatistics() {}

		/**
		 * A detailed statistics about a message.
		 *
		 * @param messageInteractionGraph A graph containing number of message views and shares.
		**/
		public MessageStatistics(StatisticalGraph messageInteractionGraph) {
			this.messageInteractionGraph = messageInteractionGraph;
		}

		/**
		 * A detailed statistics about a message.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageStatistics(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case StatisticalGraphData.CONSTRUCTOR: this.messageInteractionGraph = new StatisticalGraphData(input); break;
					case StatisticalGraphAsync.CONSTRUCTOR: this.messageInteractionGraph = new StatisticalGraphAsync(input); break;
					case StatisticalGraphError.CONSTRUCTOR: this.messageInteractionGraph = new StatisticalGraphError(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageStatistics.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageStatistics.CONSTRUCTOR);
			if (this.messageInteractionGraph == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.messageInteractionGraph.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageStatistics messageStatistics = (MessageStatistics) o;
			if (!Objects.equals(this.messageInteractionGraph, messageStatistics.messageInteractionGraph)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.messageInteractionGraph == null ? 0 : this.messageInteractionGraph.hashCode();
		}
	}

	/**
	 * Contains information about a message thread.
	**/
	public static final class MessageThreadInfo extends Object {


		/**
		 * Identifier of the chat to which the message thread belongs.
		**/
		public long chatId;

		/**
		 * Message thread identifier, unique within the chat.
		**/
		public long messageThreadId;

		/**
		 * Information about the message thread; may be null for forum topic threads.
		**/
		public MessageReplyInfo replyInfo;

		/**
		 * Approximate number of unread messages in the message thread.
		**/
		public int unreadMessageCount;

		/**
		 * The messages from which the thread starts. The messages are returned in a reverse chronological order (i.e., in order of decreasing messageId).
		**/
		public Message[] messages;

		/**
		 * A draft of a message in the message thread; may be null.
		**/
		public DraftMessage draftMessage;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -248536056;

		/**
		 * Contains information about a message thread.
		**/
		public MessageThreadInfo() {}

		/**
		 * Contains information about a message thread.
		 *
		 * @param chatId Identifier of the chat to which the message thread belongs.
		 * @param messageThreadId Message thread identifier, unique within the chat.
		 * @param replyInfo Information about the message thread; may be null for forum topic threads.
		 * @param unreadMessageCount Approximate number of unread messages in the message thread.
		 * @param messages The messages from which the thread starts. The messages are returned in a reverse chronological order (i.e., in order of decreasing messageId).
		 * @param draftMessage A draft of a message in the message thread; may be null.
		**/
		public MessageThreadInfo(long chatId,
				long messageThreadId,
				MessageReplyInfo replyInfo,
				int unreadMessageCount,
				Message[] messages,
				DraftMessage draftMessage) {
			this.chatId = chatId;
			this.messageThreadId = messageThreadId;
			this.replyInfo = replyInfo;
			this.unreadMessageCount = unreadMessageCount;
			this.messages = messages;
			this.draftMessage = draftMessage;
		}

		/**
		 * Contains information about a message thread.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageThreadInfo(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageThreadId = input.readLong();
			if (input.readBoolean()) {
				if (MessageReplyInfo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.replyInfo = new MessageReplyInfo(input);
			}
			this.unreadMessageCount = input.readInt();
			if (input.readBoolean()) {
				this.messages = new Message[input.readInt()];
				for (int i = 0; i < this.messages.length; i++) {
					if (Message.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.messages[i] = new Message(input);
				}
			}
			if (input.readBoolean()) {
				if (DraftMessage.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.draftMessage = new DraftMessage(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageThreadInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageThreadInfo.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageThreadId);
			if (this.replyInfo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.replyInfo.serialize(output);
			}
			output.writeInt(this.unreadMessageCount);
			if (this.messages == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.messages.length);
				for (int i = 0; i < this.messages.length; i++) {
					this.messages[i].serialize(output);
				}
			}
			if (this.draftMessage == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.draftMessage.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageThreadInfo messageThreadInfo = (MessageThreadInfo) o;
			if (this.chatId != messageThreadInfo.chatId) {
				return false;
			}
			if (this.messageThreadId != messageThreadInfo.messageThreadId) {
				return false;
			}
			if (!Objects.equals(this.replyInfo, messageThreadInfo.replyInfo)) {
				return false;
			}
			if (this.unreadMessageCount != messageThreadInfo.unreadMessageCount) {
				return false;
			}
			if (!Arrays.equals(this.messages, messageThreadInfo.messages)) {
				return false;
			}
			if (!Objects.equals(this.draftMessage, messageThreadInfo.draftMessage)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.replyInfo == null ? 0 : this.replyInfo.hashCode());
			result = result * 31 + (Arrays.hashCode(this.messages));
			result = result * 31 + (this.draftMessage == null ? 0 : this.draftMessage.hashCode());
			return result;
		}
	}

	/**
	 * Represents a viewer of a message.
	**/
	public static final class MessageViewer extends Object {


		/**
		 * User identifier of the viewer.
		**/
		public long userId;

		/**
		 * Approximate point in time (Unix timestamp) when the message was viewed.
		**/
		public int viewDate;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1458639309;

		/**
		 * Represents a viewer of a message.
		**/
		public MessageViewer() {}

		/**
		 * Represents a viewer of a message.
		 *
		 * @param userId User identifier of the viewer.
		 * @param viewDate Approximate point in time (Unix timestamp) when the message was viewed.
		**/
		public MessageViewer(long userId, int viewDate) {
			this.userId = userId;
			this.viewDate = viewDate;
		}

		/**
		 * Represents a viewer of a message.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageViewer(DataInput input) throws IOException {
			this.userId = input.readLong();
			this.viewDate = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageViewer.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageViewer.CONSTRUCTOR);
			output.writeLong(this.userId);
			output.writeInt(this.viewDate);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageViewer messageViewer = (MessageViewer) o;
			if (this.userId != messageViewer.userId) {
				return false;
			}
			if (this.viewDate != messageViewer.viewDate) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.userId);
			return result;
		}
	}

	/**
	 * Represents a list of message viewers.
	**/
	public static final class MessageViewers extends Object {


		/**
		 * List of message viewers.
		**/
		public MessageViewer[] viewers;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2116480287;

		/**
		 * Represents a list of message viewers.
		**/
		public MessageViewers() {}

		/**
		 * Represents a list of message viewers.
		 *
		 * @param viewers List of message viewers.
		**/
		public MessageViewers(MessageViewer[] viewers) {
			this.viewers = viewers;
		}

		/**
		 * Represents a list of message viewers.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public MessageViewers(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.viewers = new MessageViewer[input.readInt()];
				for (int i = 0; i < this.viewers.length; i++) {
					if (MessageViewer.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.viewers[i] = new MessageViewer(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return MessageViewers.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(MessageViewers.CONSTRUCTOR);
			if (this.viewers == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.viewers.length);
				for (int i = 0; i < this.viewers.length; i++) {
					this.viewers[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			MessageViewers messageViewers = (MessageViewers) o;
			if (!Arrays.equals(this.viewers, messageViewers.viewers)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.viewers);
		}
	}

	/**
	 * Contains a list of messages.
	**/
	public static final class Messages extends Object {


		/**
		 * Approximate total number of messages found.
		**/
		public int totalCount;

		/**
		 * List of messages; messages may be null.
		**/
		public Message[] messages;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -16498159;

		/**
		 * Contains a list of messages.
		**/
		public Messages() {}

		/**
		 * Contains a list of messages.
		 *
		 * @param totalCount Approximate total number of messages found.
		 * @param messages List of messages; messages may be null.
		**/
		public Messages(int totalCount, Message[] messages) {
			this.totalCount = totalCount;
			this.messages = messages;
		}

		/**
		 * Contains a list of messages.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public Messages(DataInput input) throws IOException {
			this.totalCount = input.readInt();
			if (input.readBoolean()) {
				this.messages = new Message[input.readInt()];
				for (int i = 0; i < this.messages.length; i++) {
					if (Message.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.messages[i] = new Message(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return Messages.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(Messages.CONSTRUCTOR);
			output.writeInt(this.totalCount);
			if (this.messages == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.messages.length);
				for (int i = 0; i < this.messages.length; i++) {
					this.messages[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			Messages messages = (Messages) o;
			if (this.totalCount != messages.totalCount) {
				return false;
			}
			if (!Arrays.equals(this.messages, messages.messages)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.totalCount);
			result = result * 31 + (Arrays.hashCode(this.messages));
			return result;
		}
	}

	/**
	 * Thumbnail image of a very poor quality and low resolution.
	**/
	public static final class Minithumbnail extends Object {


		/**
		 * Thumbnail width, usually doesn&#039;t exceed 40.
		**/
		public int width;

		/**
		 * Thumbnail height, usually doesn&#039;t exceed 40.
		**/
		public int height;

		/**
		 * The thumbnail in JPEG format.
		**/
		public byte[] data;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -328540758;

		/**
		 * Thumbnail image of a very poor quality and low resolution.
		**/
		public Minithumbnail() {}

		/**
		 * Thumbnail image of a very poor quality and low resolution.
		 *
		 * @param width Thumbnail width, usually doesn&#039;t exceed 40.
		 * @param height Thumbnail height, usually doesn&#039;t exceed 40.
		 * @param data The thumbnail in JPEG format.
		**/
		public Minithumbnail(int width, int height, byte[] data) {
			this.width = width;
			this.height = height;
			this.data = data;
		}

		/**
		 * Thumbnail image of a very poor quality and low resolution.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public Minithumbnail(DataInput input) throws IOException {
			this.width = input.readInt();
			this.height = input.readInt();
			if (input.readBoolean()) {
				this.data = new byte[input.readInt()];
				input.readFully(this.data);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return Minithumbnail.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(Minithumbnail.CONSTRUCTOR);
			output.writeInt(this.width);
			output.writeInt(this.height);
			if (this.data == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.data.length);
				output.write(this.data);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			Minithumbnail minithumbnail = (Minithumbnail) o;
			if (this.width != minithumbnail.width) {
				return false;
			}
			if (this.height != minithumbnail.height) {
				return false;
			}
			if (this.data != minithumbnail.data) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.width);
			result = result * 31 + (Arrays.hashCode(this.data));
			return result;
		}
	}

	/**
	 * A full list of available network statistic entries.
	**/
	public static final class NetworkStatistics extends Object {


		/**
		 * Point in time (Unix timestamp) from which the statistics are collected.
		**/
		public int sinceDate;

		/**
		 * Network statistics entries.
		**/
		public NetworkStatisticsEntry[] entries;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1615554212;

		/**
		 * A full list of available network statistic entries.
		**/
		public NetworkStatistics() {}

		/**
		 * A full list of available network statistic entries.
		 *
		 * @param sinceDate Point in time (Unix timestamp) from which the statistics are collected.
		 * @param entries Network statistics entries.
		**/
		public NetworkStatistics(int sinceDate, NetworkStatisticsEntry[] entries) {
			this.sinceDate = sinceDate;
			this.entries = entries;
		}

		/**
		 * A full list of available network statistic entries.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public NetworkStatistics(DataInput input) throws IOException {
			this.sinceDate = input.readInt();
			if (input.readBoolean()) {
				this.entries = new NetworkStatisticsEntry[input.readInt()];
				for (int i = 0; i < this.entries.length; i++) {
					switch(input.readInt()) {
						case NetworkStatisticsEntryFile.CONSTRUCTOR: this.entries[i] = new NetworkStatisticsEntryFile(input); break;
						case NetworkStatisticsEntryCall.CONSTRUCTOR: this.entries[i] = new NetworkStatisticsEntryCall(input); break;
						default: {
							throw new UnsupportedOperationException();
						}
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return NetworkStatistics.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(NetworkStatistics.CONSTRUCTOR);
			output.writeInt(this.sinceDate);
			if (this.entries == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.entries.length);
				for (int i = 0; i < this.entries.length; i++) {
					this.entries[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			NetworkStatistics networkStatistics = (NetworkStatistics) o;
			if (this.sinceDate != networkStatistics.sinceDate) {
				return false;
			}
			if (!Arrays.equals(this.entries, networkStatistics.entries)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.sinceDate);
			result = result * 31 + (Arrays.hashCode(this.entries));
			return result;
		}
	}

	/**
	 * Contains information about the total amount of data that was used to
	 * send and receive files.
	**/
	public static final class NetworkStatisticsEntryFile extends NetworkStatisticsEntry {


		/**
		 * Type of the file the data is part of; pass null if the data isn&#039;t related to files.
		**/
		public FileType fileType;

		/**
		 * Type of the network the data was sent through. Call setNetworkType to maintain the actual network type.
		**/
		public NetworkType networkType;

		/**
		 * Total number of bytes sent.
		**/
		public long sentBytes;

		/**
		 * Total number of bytes received.
		**/
		public long receivedBytes;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 188452706;

		/**
		 * Contains information about the total amount of data that was used to send and receive files.
		**/
		public NetworkStatisticsEntryFile() {}

		/**
		 * Contains information about the total amount of data that was used to send and receive files.
		 *
		 * @param fileType Type of the file the data is part of; pass null if the data isn&#039;t related to files.
		 * @param networkType Type of the network the data was sent through. Call setNetworkType to maintain the actual network type.
		 * @param sentBytes Total number of bytes sent.
		 * @param receivedBytes Total number of bytes received.
		**/
		public NetworkStatisticsEntryFile(FileType fileType,
				NetworkType networkType,
				long sentBytes,
				long receivedBytes) {
			this.fileType = fileType;
			this.networkType = networkType;
			this.sentBytes = sentBytes;
			this.receivedBytes = receivedBytes;
		}

		/**
		 * Contains information about the total amount of data that was used to send and receive files.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public NetworkStatisticsEntryFile(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case FileTypeNone.CONSTRUCTOR: this.fileType = new FileTypeNone(input); break;
					case FileTypeAnimation.CONSTRUCTOR: this.fileType = new FileTypeAnimation(input); break;
					case FileTypeAudio.CONSTRUCTOR: this.fileType = new FileTypeAudio(input); break;
					case FileTypeDocument.CONSTRUCTOR: this.fileType = new FileTypeDocument(input); break;
					case FileTypeNotificationSound.CONSTRUCTOR: this.fileType = new FileTypeNotificationSound(input); break;
					case FileTypePhoto.CONSTRUCTOR: this.fileType = new FileTypePhoto(input); break;
					case FileTypeProfilePhoto.CONSTRUCTOR: this.fileType = new FileTypeProfilePhoto(input); break;
					case FileTypeSecret.CONSTRUCTOR: this.fileType = new FileTypeSecret(input); break;
					case FileTypeSecretThumbnail.CONSTRUCTOR: this.fileType = new FileTypeSecretThumbnail(input); break;
					case FileTypeSecure.CONSTRUCTOR: this.fileType = new FileTypeSecure(input); break;
					case FileTypeSticker.CONSTRUCTOR: this.fileType = new FileTypeSticker(input); break;
					case FileTypeThumbnail.CONSTRUCTOR: this.fileType = new FileTypeThumbnail(input); break;
					case FileTypeUnknown.CONSTRUCTOR: this.fileType = new FileTypeUnknown(input); break;
					case FileTypeVideo.CONSTRUCTOR: this.fileType = new FileTypeVideo(input); break;
					case FileTypeVideoNote.CONSTRUCTOR: this.fileType = new FileTypeVideoNote(input); break;
					case FileTypeVoiceNote.CONSTRUCTOR: this.fileType = new FileTypeVoiceNote(input); break;
					case FileTypeWallpaper.CONSTRUCTOR: this.fileType = new FileTypeWallpaper(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case NetworkTypeNone.CONSTRUCTOR: this.networkType = new NetworkTypeNone(input); break;
					case NetworkTypeMobile.CONSTRUCTOR: this.networkType = new NetworkTypeMobile(input); break;
					case NetworkTypeMobileRoaming.CONSTRUCTOR: this.networkType = new NetworkTypeMobileRoaming(input); break;
					case NetworkTypeWiFi.CONSTRUCTOR: this.networkType = new NetworkTypeWiFi(input); break;
					case NetworkTypeOther.CONSTRUCTOR: this.networkType = new NetworkTypeOther(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.sentBytes = input.readLong();
			this.receivedBytes = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return NetworkStatisticsEntryFile.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(NetworkStatisticsEntryFile.CONSTRUCTOR);
			if (this.fileType == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.fileType.serialize(output);
			}
			if (this.networkType == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.networkType.serialize(output);
			}
			output.writeLong(this.sentBytes);
			output.writeLong(this.receivedBytes);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			NetworkStatisticsEntryFile networkStatisticsEntryFile = (NetworkStatisticsEntryFile) o;
			if (!Objects.equals(this.fileType, networkStatisticsEntryFile.fileType)) {
				return false;
			}
			if (!Objects.equals(this.networkType, networkStatisticsEntryFile.networkType)) {
				return false;
			}
			if (this.sentBytes != networkStatisticsEntryFile.sentBytes) {
				return false;
			}
			if (this.receivedBytes != networkStatisticsEntryFile.receivedBytes) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.sentBytes);
			result = result * 31 + (this.fileType == null ? 0 : this.fileType.hashCode());
			result = result * 31 + (this.networkType == null ? 0 : this.networkType.hashCode());
			return result;
		}
	}

	/**
	 * Contains information about the total amount of data that was used for
	 * calls.
	**/
	public static final class NetworkStatisticsEntryCall extends NetworkStatisticsEntry {


		/**
		 * Type of the network the data was sent through. Call setNetworkType to maintain the actual network type.
		**/
		public NetworkType networkType;

		/**
		 * Total number of bytes sent.
		**/
		public long sentBytes;

		/**
		 * Total number of bytes received.
		**/
		public long receivedBytes;

		/**
		 * Total call duration, in seconds.
		**/
		public double duration;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 737000365;

		/**
		 * Contains information about the total amount of data that was used for calls.
		**/
		public NetworkStatisticsEntryCall() {}

		/**
		 * Contains information about the total amount of data that was used for calls.
		 *
		 * @param networkType Type of the network the data was sent through. Call setNetworkType to maintain the actual network type.
		 * @param sentBytes Total number of bytes sent.
		 * @param receivedBytes Total number of bytes received.
		 * @param duration Total call duration, in seconds.
		**/
		public NetworkStatisticsEntryCall(NetworkType networkType,
				long sentBytes,
				long receivedBytes,
				double duration) {
			this.networkType = networkType;
			this.sentBytes = sentBytes;
			this.receivedBytes = receivedBytes;
			this.duration = duration;
		}

		/**
		 * Contains information about the total amount of data that was used for calls.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public NetworkStatisticsEntryCall(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case NetworkTypeNone.CONSTRUCTOR: this.networkType = new NetworkTypeNone(input); break;
					case NetworkTypeMobile.CONSTRUCTOR: this.networkType = new NetworkTypeMobile(input); break;
					case NetworkTypeMobileRoaming.CONSTRUCTOR: this.networkType = new NetworkTypeMobileRoaming(input); break;
					case NetworkTypeWiFi.CONSTRUCTOR: this.networkType = new NetworkTypeWiFi(input); break;
					case NetworkTypeOther.CONSTRUCTOR: this.networkType = new NetworkTypeOther(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.sentBytes = input.readLong();
			this.receivedBytes = input.readLong();
			this.duration = input.readDouble();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return NetworkStatisticsEntryCall.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(NetworkStatisticsEntryCall.CONSTRUCTOR);
			if (this.networkType == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.networkType.serialize(output);
			}
			output.writeLong(this.sentBytes);
			output.writeLong(this.receivedBytes);
			output.writeDouble(this.duration);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			NetworkStatisticsEntryCall networkStatisticsEntryCall = (NetworkStatisticsEntryCall) o;
			if (!Objects.equals(this.networkType, networkStatisticsEntryCall.networkType)) {
				return false;
			}
			if (this.sentBytes != networkStatisticsEntryCall.sentBytes) {
				return false;
			}
			if (this.receivedBytes != networkStatisticsEntryCall.receivedBytes) {
				return false;
			}
			if (this.duration != networkStatisticsEntryCall.duration) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.sentBytes);
			result = result * 31 + (this.networkType == null ? 0 : this.networkType.hashCode());
			return result;
		}
	}

	/**
	 * The network is not available.
	**/
	public static final class NetworkTypeNone extends NetworkType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1971691759;

		/**
		 * The network is not available.
		**/
		public NetworkTypeNone() {}

		/**
		 * The network is not available.
		 *
		**/

		/**
		 * The network is not available.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public NetworkTypeNone(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return NetworkTypeNone.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(NetworkTypeNone.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return NetworkTypeNone.CONSTRUCTOR;
		}
	}

	/**
	 * A mobile network.
	**/
	public static final class NetworkTypeMobile extends NetworkType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 819228239;

		/**
		 * A mobile network.
		**/
		public NetworkTypeMobile() {}

		/**
		 * A mobile network.
		 *
		**/

		/**
		 * A mobile network.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public NetworkTypeMobile(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return NetworkTypeMobile.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(NetworkTypeMobile.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return NetworkTypeMobile.CONSTRUCTOR;
		}
	}

	/**
	 * A mobile roaming network.
	**/
	public static final class NetworkTypeMobileRoaming extends NetworkType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1435199760;

		/**
		 * A mobile roaming network.
		**/
		public NetworkTypeMobileRoaming() {}

		/**
		 * A mobile roaming network.
		 *
		**/

		/**
		 * A mobile roaming network.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public NetworkTypeMobileRoaming(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return NetworkTypeMobileRoaming.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(NetworkTypeMobileRoaming.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return NetworkTypeMobileRoaming.CONSTRUCTOR;
		}
	}

	/**
	 * A Wi-Fi network.
	**/
	public static final class NetworkTypeWiFi extends NetworkType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -633872070;

		/**
		 * A Wi-Fi network.
		**/
		public NetworkTypeWiFi() {}

		/**
		 * A Wi-Fi network.
		 *
		**/

		/**
		 * A Wi-Fi network.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public NetworkTypeWiFi(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return NetworkTypeWiFi.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(NetworkTypeWiFi.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return NetworkTypeWiFi.CONSTRUCTOR;
		}
	}

	/**
	 * A different network type (e.g., Ethernet network).
	**/
	public static final class NetworkTypeOther extends NetworkType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1942128539;

		/**
		 * A different network type (e.g., Ethernet network).
		**/
		public NetworkTypeOther() {}

		/**
		 * A different network type (e.g., Ethernet network).
		 *
		**/

		/**
		 * A different network type (e.g., Ethernet network).
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public NetworkTypeOther(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return NetworkTypeOther.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(NetworkTypeOther.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return NetworkTypeOther.CONSTRUCTOR;
		}
	}

	/**
	 * Contains information about a notification.
	**/
	public static final class Notification extends Object {


		/**
		 * Unique persistent identifier of this notification.
		**/
		public int id;

		/**
		 * Notification date.
		**/
		public int date;

		/**
		 * True, if the notification was explicitly sent without sound.
		**/
		public boolean isSilent;

		/**
		 * Notification type.
		**/
		public NotificationType type;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 788743120;

		/**
		 * Contains information about a notification.
		**/
		public Notification() {}

		/**
		 * Contains information about a notification.
		 *
		 * @param id Unique persistent identifier of this notification.
		 * @param date Notification date.
		 * @param isSilent True, if the notification was explicitly sent without sound.
		 * @param type Notification type.
		**/
		public Notification(int id, int date, boolean isSilent, NotificationType type) {
			this.id = id;
			this.date = date;
			this.isSilent = isSilent;
			this.type = type;
		}

		/**
		 * Contains information about a notification.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public Notification(DataInput input) throws IOException {
			this.id = input.readInt();
			this.date = input.readInt();
			this.isSilent = input.readBoolean();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case NotificationTypeNewMessage.CONSTRUCTOR: this.type = new NotificationTypeNewMessage(input); break;
					case NotificationTypeNewSecretChat.CONSTRUCTOR: this.type = new NotificationTypeNewSecretChat(input); break;
					case NotificationTypeNewCall.CONSTRUCTOR: this.type = new NotificationTypeNewCall(input); break;
					case NotificationTypeNewPushMessage.CONSTRUCTOR: this.type = new NotificationTypeNewPushMessage(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return Notification.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(Notification.CONSTRUCTOR);
			output.writeInt(this.id);
			output.writeInt(this.date);
			output.writeBoolean(this.isSilent);
			if (this.type == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.type.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			Notification notification = (Notification) o;
			if (this.id != notification.id) {
				return false;
			}
			if (this.date != notification.date) {
				return false;
			}
			if (this.isSilent != notification.isSilent) {
				return false;
			}
			if (!Objects.equals(this.type, notification.type)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.id);
			result = result * 31 + (this.type == null ? 0 : this.type.hashCode());
			return result;
		}
	}

	/**
	 * Describes a group of notifications.
	**/
	public static final class NotificationGroup extends Object {


		/**
		 * Unique persistent auto-incremented from 1 identifier of the notification group.
		**/
		public int id;

		/**
		 * Type of the group.
		**/
		public NotificationGroupType type;

		/**
		 * Identifier of a chat to which all notifications in the group belong.
		**/
		public long chatId;

		/**
		 * Total number of active notifications in the group.
		**/
		public int totalCount;

		/**
		 * The list of active notifications.
		**/
		public Notification[] notifications;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 780691541;

		/**
		 * Describes a group of notifications.
		**/
		public NotificationGroup() {}

		/**
		 * Describes a group of notifications.
		 *
		 * @param id Unique persistent auto-incremented from 1 identifier of the notification group.
		 * @param type Type of the group.
		 * @param chatId Identifier of a chat to which all notifications in the group belong.
		 * @param totalCount Total number of active notifications in the group.
		 * @param notifications The list of active notifications.
		**/
		public NotificationGroup(int id,
				NotificationGroupType type,
				long chatId,
				int totalCount,
				Notification[] notifications) {
			this.id = id;
			this.type = type;
			this.chatId = chatId;
			this.totalCount = totalCount;
			this.notifications = notifications;
		}

		/**
		 * Describes a group of notifications.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public NotificationGroup(DataInput input) throws IOException {
			this.id = input.readInt();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case NotificationGroupTypeMessages.CONSTRUCTOR: this.type = new NotificationGroupTypeMessages(input); break;
					case NotificationGroupTypeMentions.CONSTRUCTOR: this.type = new NotificationGroupTypeMentions(input); break;
					case NotificationGroupTypeSecretChat.CONSTRUCTOR: this.type = new NotificationGroupTypeSecretChat(input); break;
					case NotificationGroupTypeCalls.CONSTRUCTOR: this.type = new NotificationGroupTypeCalls(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.chatId = input.readLong();
			this.totalCount = input.readInt();
			if (input.readBoolean()) {
				this.notifications = new Notification[input.readInt()];
				for (int i = 0; i < this.notifications.length; i++) {
					if (Notification.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.notifications[i] = new Notification(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return NotificationGroup.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(NotificationGroup.CONSTRUCTOR);
			output.writeInt(this.id);
			if (this.type == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.type.serialize(output);
			}
			output.writeLong(this.chatId);
			output.writeInt(this.totalCount);
			if (this.notifications == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.notifications.length);
				for (int i = 0; i < this.notifications.length; i++) {
					this.notifications[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			NotificationGroup notificationGroup = (NotificationGroup) o;
			if (this.id != notificationGroup.id) {
				return false;
			}
			if (!Objects.equals(this.type, notificationGroup.type)) {
				return false;
			}
			if (this.chatId != notificationGroup.chatId) {
				return false;
			}
			if (this.totalCount != notificationGroup.totalCount) {
				return false;
			}
			if (!Arrays.equals(this.notifications, notificationGroup.notifications)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.id);
			result = result * 31 + (this.type == null ? 0 : this.type.hashCode());
			result = result * 31 + (Arrays.hashCode(this.notifications));
			return result;
		}
	}

	/**
	 * A group containing notifications of type notificationTypeNewMessage
	 * and notificationTypeNewPushMessage with ordinary unread messages.
	**/
	public static final class NotificationGroupTypeMessages extends NotificationGroupType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1702481123;

		/**
		 * A group containing notifications of type notificationTypeNewMessage and notificationTypeNewPushMessage with ordinary unread messages.
		**/
		public NotificationGroupTypeMessages() {}

		/**
		 * A group containing notifications of type notificationTypeNewMessage and notificationTypeNewPushMessage with ordinary unread messages.
		 *
		**/

		/**
		 * A group containing notifications of type notificationTypeNewMessage and notificationTypeNewPushMessage with ordinary unread messages.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public NotificationGroupTypeMessages(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return NotificationGroupTypeMessages.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(NotificationGroupTypeMessages.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return NotificationGroupTypeMessages.CONSTRUCTOR;
		}
	}

	/**
	 * A group containing notifications of type notificationTypeNewMessage
	 * and notificationTypeNewPushMessage with unread mentions of the
	 * current user, replies to their messages, or a pinned message.
	**/
	public static final class NotificationGroupTypeMentions extends NotificationGroupType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2050324051;

		/**
		 * A group containing notifications of type notificationTypeNewMessage and notificationTypeNewPushMessage with unread mentions of the current user, replies to their messages, or a pinned message.
		**/
		public NotificationGroupTypeMentions() {}

		/**
		 * A group containing notifications of type notificationTypeNewMessage and notificationTypeNewPushMessage with unread mentions of the current user, replies to their messages, or a pinned message.
		 *
		**/

		/**
		 * A group containing notifications of type notificationTypeNewMessage and notificationTypeNewPushMessage with unread mentions of the current user, replies to their messages, or a pinned message.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public NotificationGroupTypeMentions(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return NotificationGroupTypeMentions.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(NotificationGroupTypeMentions.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return NotificationGroupTypeMentions.CONSTRUCTOR;
		}
	}

	/**
	 * A group containing a notification of type
	 * notificationTypeNewSecretChat.
	**/
	public static final class NotificationGroupTypeSecretChat extends NotificationGroupType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1390759476;

		/**
		 * A group containing a notification of type notificationTypeNewSecretChat.
		**/
		public NotificationGroupTypeSecretChat() {}

		/**
		 * A group containing a notification of type notificationTypeNewSecretChat.
		 *
		**/

		/**
		 * A group containing a notification of type notificationTypeNewSecretChat.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public NotificationGroupTypeSecretChat(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return NotificationGroupTypeSecretChat.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(NotificationGroupTypeSecretChat.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return NotificationGroupTypeSecretChat.CONSTRUCTOR;
		}
	}

	/**
	 * A group containing notifications of type notificationTypeNewCall.
	**/
	public static final class NotificationGroupTypeCalls extends NotificationGroupType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1379123538;

		/**
		 * A group containing notifications of type notificationTypeNewCall.
		**/
		public NotificationGroupTypeCalls() {}

		/**
		 * A group containing notifications of type notificationTypeNewCall.
		 *
		**/

		/**
		 * A group containing notifications of type notificationTypeNewCall.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public NotificationGroupTypeCalls(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return NotificationGroupTypeCalls.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(NotificationGroupTypeCalls.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return NotificationGroupTypeCalls.CONSTRUCTOR;
		}
	}

	/**
	 * Notification settings applied to all private and secret chats when
	 * the corresponding chat setting has a default value.
	**/
	public static final class NotificationSettingsScopePrivateChats extends NotificationSettingsScope {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 937446759;

		/**
		 * Notification settings applied to all private and secret chats when the corresponding chat setting has a default value.
		**/
		public NotificationSettingsScopePrivateChats() {}

		/**
		 * Notification settings applied to all private and secret chats when the corresponding chat setting has a default value.
		 *
		**/

		/**
		 * Notification settings applied to all private and secret chats when the corresponding chat setting has a default value.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public NotificationSettingsScopePrivateChats(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return NotificationSettingsScopePrivateChats.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(NotificationSettingsScopePrivateChats.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return NotificationSettingsScopePrivateChats.CONSTRUCTOR;
		}
	}

	/**
	 * Notification settings applied to all basic group and supergroup chats
	 * when the corresponding chat setting has a default value.
	**/
	public static final class NotificationSettingsScopeGroupChats extends NotificationSettingsScope {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1212142067;

		/**
		 * Notification settings applied to all basic group and supergroup chats when the corresponding chat setting has a default value.
		**/
		public NotificationSettingsScopeGroupChats() {}

		/**
		 * Notification settings applied to all basic group and supergroup chats when the corresponding chat setting has a default value.
		 *
		**/

		/**
		 * Notification settings applied to all basic group and supergroup chats when the corresponding chat setting has a default value.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public NotificationSettingsScopeGroupChats(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return NotificationSettingsScopeGroupChats.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(NotificationSettingsScopeGroupChats.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return NotificationSettingsScopeGroupChats.CONSTRUCTOR;
		}
	}

	/**
	 * Notification settings applied to all channel chats when the
	 * corresponding chat setting has a default value.
	**/
	public static final class NotificationSettingsScopeChannelChats extends NotificationSettingsScope {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 548013448;

		/**
		 * Notification settings applied to all channel chats when the corresponding chat setting has a default value.
		**/
		public NotificationSettingsScopeChannelChats() {}

		/**
		 * Notification settings applied to all channel chats when the corresponding chat setting has a default value.
		 *
		**/

		/**
		 * Notification settings applied to all channel chats when the corresponding chat setting has a default value.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public NotificationSettingsScopeChannelChats(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return NotificationSettingsScopeChannelChats.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(NotificationSettingsScopeChannelChats.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return NotificationSettingsScopeChannelChats.CONSTRUCTOR;
		}
	}

	/**
	 * Describes a notification sound in MP3 format.
	**/
	public static final class NotificationSound extends Object {


		/**
		 * Unique identifier of the notification sound.
		**/
		public long id;

		/**
		 * Duration of the sound, in seconds.
		**/
		public int duration;

		/**
		 * Point in time (Unix timestamp) when the sound was created.
		**/
		public int date;

		/**
		 * Title of the notification sound.
		**/
		public String title;

		/**
		 * Arbitrary data, defined while the sound was uploaded.
		**/
		public String data;

		/**
		 * File containing the sound.
		**/
		public File sound;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -185638601;

		/**
		 * Describes a notification sound in MP3 format.
		**/
		public NotificationSound() {}

		/**
		 * Describes a notification sound in MP3 format.
		 *
		 * @param id Unique identifier of the notification sound.
		 * @param duration Duration of the sound, in seconds.
		 * @param date Point in time (Unix timestamp) when the sound was created.
		 * @param title Title of the notification sound.
		 * @param data Arbitrary data, defined while the sound was uploaded.
		 * @param sound File containing the sound.
		**/
		public NotificationSound(long id,
				int duration,
				int date,
				String title,
				String data,
				File sound) {
			this.id = id;
			this.duration = duration;
			this.date = date;
			this.title = title;
			this.data = data;
			this.sound = sound;
		}

		/**
		 * Describes a notification sound in MP3 format.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public NotificationSound(DataInput input) throws IOException {
			this.id = input.readLong();
			this.duration = input.readInt();
			this.date = input.readInt();
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] dataTmp = new byte[input.readInt()];
				input.readFully(dataTmp);
				this.data = new String(dataTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (File.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.sound = new File(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return NotificationSound.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(NotificationSound.CONSTRUCTOR);
			output.writeLong(this.id);
			output.writeInt(this.duration);
			output.writeInt(this.date);
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
			if (this.data == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] dataTmp = this.data.getBytes(StandardCharsets.UTF_8);
				output.writeInt(dataTmp.length);
				output.write(dataTmp);
			}
			if (this.sound == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.sound.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			NotificationSound notificationSound = (NotificationSound) o;
			if (this.id != notificationSound.id) {
				return false;
			}
			if (this.duration != notificationSound.duration) {
				return false;
			}
			if (this.date != notificationSound.date) {
				return false;
			}
			if (this.title != notificationSound.title) {
				return false;
			}
			if (this.data != notificationSound.data) {
				return false;
			}
			if (!Objects.equals(this.sound, notificationSound.sound)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.id);
			result = result * 31 + (this.title == null ? 0 : this.title.hashCode());
			result = result * 31 + (this.data == null ? 0 : this.data.hashCode());
			result = result * 31 + (this.sound == null ? 0 : this.sound.hashCode());
			return result;
		}
	}

	/**
	 * Contains a list of notification sounds.
	**/
	public static final class NotificationSounds extends Object {


		/**
		 * A list of notification sounds.
		**/
		public NotificationSound[] notificationSounds;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -630813169;

		/**
		 * Contains a list of notification sounds.
		**/
		public NotificationSounds() {}

		/**
		 * Contains a list of notification sounds.
		 *
		 * @param notificationSounds A list of notification sounds.
		**/
		public NotificationSounds(NotificationSound[] notificationSounds) {
			this.notificationSounds = notificationSounds;
		}

		/**
		 * Contains a list of notification sounds.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public NotificationSounds(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.notificationSounds = new NotificationSound[input.readInt()];
				for (int i = 0; i < this.notificationSounds.length; i++) {
					if (NotificationSound.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.notificationSounds[i] = new NotificationSound(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return NotificationSounds.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(NotificationSounds.CONSTRUCTOR);
			if (this.notificationSounds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.notificationSounds.length);
				for (int i = 0; i < this.notificationSounds.length; i++) {
					this.notificationSounds[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			NotificationSounds notificationSounds = (NotificationSounds) o;
			if (!Arrays.equals(this.notificationSounds, notificationSounds.notificationSounds)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.notificationSounds);
		}
	}

	/**
	 * New message was received.
	**/
	public static final class NotificationTypeNewMessage extends NotificationType {


		/**
		 * The message.
		**/
		public Message message;

		/**
		 * True, if message content must be displayed in notifications.
		**/
		public boolean showPreview;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -254745614;

		/**
		 * New message was received.
		**/
		public NotificationTypeNewMessage() {}

		/**
		 * New message was received.
		 *
		 * @param message The message.
		 * @param showPreview True, if message content must be displayed in notifications.
		**/
		public NotificationTypeNewMessage(Message message, boolean showPreview) {
			this.message = message;
			this.showPreview = showPreview;
		}

		/**
		 * New message was received.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public NotificationTypeNewMessage(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Message.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.message = new Message(input);
			}
			this.showPreview = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return NotificationTypeNewMessage.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(NotificationTypeNewMessage.CONSTRUCTOR);
			if (this.message == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.message.serialize(output);
			}
			output.writeBoolean(this.showPreview);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			NotificationTypeNewMessage notificationTypeNewMessage = (NotificationTypeNewMessage) o;
			if (!Objects.equals(this.message, notificationTypeNewMessage.message)) {
				return false;
			}
			if (this.showPreview != notificationTypeNewMessage.showPreview) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.showPreview);
			result = result * 31 + (this.message == null ? 0 : this.message.hashCode());
			return result;
		}
	}

	/**
	 * New secret chat was created.
	**/
	public static final class NotificationTypeNewSecretChat extends NotificationType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1198638768;

		/**
		 * New secret chat was created.
		**/
		public NotificationTypeNewSecretChat() {}

		/**
		 * New secret chat was created.
		 *
		**/

		/**
		 * New secret chat was created.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public NotificationTypeNewSecretChat(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return NotificationTypeNewSecretChat.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(NotificationTypeNewSecretChat.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return NotificationTypeNewSecretChat.CONSTRUCTOR;
		}
	}

	/**
	 * New call was received.
	**/
	public static final class NotificationTypeNewCall extends NotificationType {


		/**
		 * Call identifier.
		**/
		public int callId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1712734585;

		/**
		 * New call was received.
		**/
		public NotificationTypeNewCall() {}

		/**
		 * New call was received.
		 *
		 * @param callId Call identifier.
		**/
		public NotificationTypeNewCall(int callId) {
			this.callId = callId;
		}

		/**
		 * New call was received.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public NotificationTypeNewCall(DataInput input) throws IOException {
			this.callId = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return NotificationTypeNewCall.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(NotificationTypeNewCall.CONSTRUCTOR);
			output.writeInt(this.callId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			NotificationTypeNewCall notificationTypeNewCall = (NotificationTypeNewCall) o;
			if (this.callId != notificationTypeNewCall.callId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.callId);
		}
	}

	/**
	 * New message was received through a push notification.
	**/
	public static final class NotificationTypeNewPushMessage extends NotificationType {


		/**
		 * The message identifier. The message will not be available in the chat history, but the ID can be used in viewMessages, or as replyToMessageId.
		**/
		public long messageId;

		/**
		 * Identifier of the sender of the message. Corresponding user or chat may be inaccessible.
		**/
		public MessageSender senderId;

		/**
		 * Name of the sender.
		**/
		public String senderName;

		/**
		 * True, if the message is outgoing.
		**/
		public boolean isOutgoing;

		/**
		 * Push message content.
		**/
		public PushMessageContent content;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -711680462;

		/**
		 * New message was received through a push notification.
		**/
		public NotificationTypeNewPushMessage() {}

		/**
		 * New message was received through a push notification.
		 *
		 * @param messageId The message identifier. The message will not be available in the chat history, but the ID can be used in viewMessages, or as replyToMessageId.
		 * @param senderId Identifier of the sender of the message. Corresponding user or chat may be inaccessible.
		 * @param senderName Name of the sender.
		 * @param isOutgoing True, if the message is outgoing.
		 * @param content Push message content.
		**/
		public NotificationTypeNewPushMessage(long messageId,
				MessageSender senderId,
				String senderName,
				boolean isOutgoing,
				PushMessageContent content) {
			this.messageId = messageId;
			this.senderId = senderId;
			this.senderName = senderName;
			this.isOutgoing = isOutgoing;
			this.content = content;
		}

		/**
		 * New message was received through a push notification.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public NotificationTypeNewPushMessage(DataInput input) throws IOException {
			this.messageId = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case MessageSenderUser.CONSTRUCTOR: this.senderId = new MessageSenderUser(input); break;
					case MessageSenderChat.CONSTRUCTOR: this.senderId = new MessageSenderChat(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				byte[] senderNameTmp = new byte[input.readInt()];
				input.readFully(senderNameTmp);
				this.senderName = new String(senderNameTmp, StandardCharsets.UTF_8);
			}
			this.isOutgoing = input.readBoolean();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case PushMessageContentHidden.CONSTRUCTOR: this.content = new PushMessageContentHidden(input); break;
					case PushMessageContentAnimation.CONSTRUCTOR: this.content = new PushMessageContentAnimation(input); break;
					case PushMessageContentAudio.CONSTRUCTOR: this.content = new PushMessageContentAudio(input); break;
					case PushMessageContentContact.CONSTRUCTOR: this.content = new PushMessageContentContact(input); break;
					case PushMessageContentContactRegistered.CONSTRUCTOR: this.content = new PushMessageContentContactRegistered(input); break;
					case PushMessageContentDocument.CONSTRUCTOR: this.content = new PushMessageContentDocument(input); break;
					case PushMessageContentGame.CONSTRUCTOR: this.content = new PushMessageContentGame(input); break;
					case PushMessageContentGameScore.CONSTRUCTOR: this.content = new PushMessageContentGameScore(input); break;
					case PushMessageContentInvoice.CONSTRUCTOR: this.content = new PushMessageContentInvoice(input); break;
					case PushMessageContentLocation.CONSTRUCTOR: this.content = new PushMessageContentLocation(input); break;
					case PushMessageContentPhoto.CONSTRUCTOR: this.content = new PushMessageContentPhoto(input); break;
					case PushMessageContentPoll.CONSTRUCTOR: this.content = new PushMessageContentPoll(input); break;
					case PushMessageContentScreenshotTaken.CONSTRUCTOR: this.content = new PushMessageContentScreenshotTaken(input); break;
					case PushMessageContentSticker.CONSTRUCTOR: this.content = new PushMessageContentSticker(input); break;
					case PushMessageContentText.CONSTRUCTOR: this.content = new PushMessageContentText(input); break;
					case PushMessageContentVideo.CONSTRUCTOR: this.content = new PushMessageContentVideo(input); break;
					case PushMessageContentVideoNote.CONSTRUCTOR: this.content = new PushMessageContentVideoNote(input); break;
					case PushMessageContentVoiceNote.CONSTRUCTOR: this.content = new PushMessageContentVoiceNote(input); break;
					case PushMessageContentBasicGroupChatCreate.CONSTRUCTOR: this.content = new PushMessageContentBasicGroupChatCreate(input); break;
					case PushMessageContentChatAddMembers.CONSTRUCTOR: this.content = new PushMessageContentChatAddMembers(input); break;
					case PushMessageContentChatChangePhoto.CONSTRUCTOR: this.content = new PushMessageContentChatChangePhoto(input); break;
					case PushMessageContentChatChangeTitle.CONSTRUCTOR: this.content = new PushMessageContentChatChangeTitle(input); break;
					case PushMessageContentChatSetBackground.CONSTRUCTOR: this.content = new PushMessageContentChatSetBackground(input); break;
					case PushMessageContentChatSetTheme.CONSTRUCTOR: this.content = new PushMessageContentChatSetTheme(input); break;
					case PushMessageContentChatDeleteMember.CONSTRUCTOR: this.content = new PushMessageContentChatDeleteMember(input); break;
					case PushMessageContentChatJoinByLink.CONSTRUCTOR: this.content = new PushMessageContentChatJoinByLink(input); break;
					case PushMessageContentChatJoinByRequest.CONSTRUCTOR: this.content = new PushMessageContentChatJoinByRequest(input); break;
					case PushMessageContentRecurringPayment.CONSTRUCTOR: this.content = new PushMessageContentRecurringPayment(input); break;
					case PushMessageContentSuggestProfilePhoto.CONSTRUCTOR: this.content = new PushMessageContentSuggestProfilePhoto(input); break;
					case PushMessageContentMessageForwards.CONSTRUCTOR: this.content = new PushMessageContentMessageForwards(input); break;
					case PushMessageContentMediaAlbum.CONSTRUCTOR: this.content = new PushMessageContentMediaAlbum(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return NotificationTypeNewPushMessage.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(NotificationTypeNewPushMessage.CONSTRUCTOR);
			output.writeLong(this.messageId);
			if (this.senderId == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.senderId.serialize(output);
			}
			if (this.senderName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] senderNameTmp = this.senderName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(senderNameTmp.length);
				output.write(senderNameTmp);
			}
			output.writeBoolean(this.isOutgoing);
			if (this.content == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.content.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			NotificationTypeNewPushMessage notificationTypeNewPushMessage = (NotificationTypeNewPushMessage) o;
			if (this.messageId != notificationTypeNewPushMessage.messageId) {
				return false;
			}
			if (!Objects.equals(this.senderId, notificationTypeNewPushMessage.senderId)) {
				return false;
			}
			if (this.senderName != notificationTypeNewPushMessage.senderName) {
				return false;
			}
			if (this.isOutgoing != notificationTypeNewPushMessage.isOutgoing) {
				return false;
			}
			if (!Objects.equals(this.content, notificationTypeNewPushMessage.content)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.messageId);
			result = result * 31 + (this.senderId == null ? 0 : this.senderId.hashCode());
			result = result * 31 + (this.senderName == null ? 0 : this.senderName.hashCode());
			result = result * 31 + (this.content == null ? 0 : this.content.hashCode());
			return result;
		}
	}

	/**
	 * An object of this type is returned on a successful function call for
	 * certain functions.
	**/
	public static final class Ok extends Object {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -722616727;

		/**
		 * An object of this type is returned on a successful function call for certain functions.
		**/
		public Ok() {}

		/**
		 * An object of this type is returned on a successful function call for certain functions.
		 *
		**/

		/**
		 * An object of this type is returned on a successful function call for certain functions.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public Ok(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return Ok.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(Ok.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Ok.CONSTRUCTOR;
		}
	}

	/**
	 * Represents a boolean option.
	**/
	public static final class OptionValueBoolean extends OptionValue {


		/**
		 * The value of the option.
		**/
		public boolean value;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 63135518;

		/**
		 * Represents a boolean option.
		**/
		public OptionValueBoolean() {}

		/**
		 * Represents a boolean option.
		 *
		 * @param value The value of the option.
		**/
		public OptionValueBoolean(boolean value) {
			this.value = value;
		}

		/**
		 * Represents a boolean option.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public OptionValueBoolean(DataInput input) throws IOException {
			this.value = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return OptionValueBoolean.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(OptionValueBoolean.CONSTRUCTOR);
			output.writeBoolean(this.value);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			OptionValueBoolean optionValueBoolean = (OptionValueBoolean) o;
			if (this.value != optionValueBoolean.value) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Boolean.hashCode(this.value);
		}
	}

	/**
	 * Represents an unknown option or an option which has a default value.
	**/
	public static final class OptionValueEmpty extends OptionValue {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 918955155;

		/**
		 * Represents an unknown option or an option which has a default value.
		**/
		public OptionValueEmpty() {}

		/**
		 * Represents an unknown option or an option which has a default value.
		 *
		**/

		/**
		 * Represents an unknown option or an option which has a default value.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public OptionValueEmpty(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return OptionValueEmpty.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(OptionValueEmpty.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return OptionValueEmpty.CONSTRUCTOR;
		}
	}

	/**
	 * Represents an integer option.
	**/
	public static final class OptionValueInteger extends OptionValue {


		/**
		 * The value of the option.
		**/
		public long value;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -186858780;

		/**
		 * Represents an integer option.
		**/
		public OptionValueInteger() {}

		/**
		 * Represents an integer option.
		 *
		 * @param value The value of the option.
		**/
		public OptionValueInteger(long value) {
			this.value = value;
		}

		/**
		 * Represents an integer option.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public OptionValueInteger(DataInput input) throws IOException {
			this.value = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return OptionValueInteger.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(OptionValueInteger.CONSTRUCTOR);
			output.writeLong(this.value);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			OptionValueInteger optionValueInteger = (OptionValueInteger) o;
			if (this.value != optionValueInteger.value) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.value);
		}
	}

	/**
	 * Represents a string option.
	**/
	public static final class OptionValueString extends OptionValue {


		/**
		 * The value of the option.
		**/
		public String value;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 756248212;

		/**
		 * Represents a string option.
		**/
		public OptionValueString() {}

		/**
		 * Represents a string option.
		 *
		 * @param value The value of the option.
		**/
		public OptionValueString(String value) {
			this.value = value;
		}

		/**
		 * Represents a string option.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public OptionValueString(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] valueTmp = new byte[input.readInt()];
				input.readFully(valueTmp);
				this.value = new String(valueTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return OptionValueString.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(OptionValueString.CONSTRUCTOR);
			if (this.value == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] valueTmp = this.value.getBytes(StandardCharsets.UTF_8);
				output.writeInt(valueTmp.length);
				output.write(valueTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			OptionValueString optionValueString = (OptionValueString) o;
			if (this.value != optionValueString.value) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.value == null ? 0 : this.value.hashCode();
		}
	}

	/**
	 * Order information.
	**/
	public static final class OrderInfo extends Object {


		/**
		 * Name of the user.
		**/
		public String name;

		/**
		 * Phone number of the user.
		**/
		public String phoneNumber;

		/**
		 * Email address of the user.
		**/
		public String emailAddress;

		/**
		 * Shipping address for this order; may be null.
		**/
		public Address shippingAddress;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 783997294;

		/**
		 * Order information.
		**/
		public OrderInfo() {}

		/**
		 * Order information.
		 *
		 * @param name Name of the user.
		 * @param phoneNumber Phone number of the user.
		 * @param emailAddress Email address of the user.
		 * @param shippingAddress Shipping address for this order; may be null.
		**/
		public OrderInfo(String name,
				String phoneNumber,
				String emailAddress,
				Address shippingAddress) {
			this.name = name;
			this.phoneNumber = phoneNumber;
			this.emailAddress = emailAddress;
			this.shippingAddress = shippingAddress;
		}

		/**
		 * Order information.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public OrderInfo(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] nameTmp = new byte[input.readInt()];
				input.readFully(nameTmp);
				this.name = new String(nameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] phoneNumberTmp = new byte[input.readInt()];
				input.readFully(phoneNumberTmp);
				this.phoneNumber = new String(phoneNumberTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] emailAddressTmp = new byte[input.readInt()];
				input.readFully(emailAddressTmp);
				this.emailAddress = new String(emailAddressTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (Address.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.shippingAddress = new Address(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return OrderInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(OrderInfo.CONSTRUCTOR);
			if (this.name == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nameTmp = this.name.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nameTmp.length);
				output.write(nameTmp);
			}
			if (this.phoneNumber == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] phoneNumberTmp = this.phoneNumber.getBytes(StandardCharsets.UTF_8);
				output.writeInt(phoneNumberTmp.length);
				output.write(phoneNumberTmp);
			}
			if (this.emailAddress == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] emailAddressTmp = this.emailAddress.getBytes(StandardCharsets.UTF_8);
				output.writeInt(emailAddressTmp.length);
				output.write(emailAddressTmp);
			}
			if (this.shippingAddress == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.shippingAddress.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			OrderInfo orderInfo = (OrderInfo) o;
			if (this.name != orderInfo.name) {
				return false;
			}
			if (this.phoneNumber != orderInfo.phoneNumber) {
				return false;
			}
			if (this.emailAddress != orderInfo.emailAddress) {
				return false;
			}
			if (!Objects.equals(this.shippingAddress, orderInfo.shippingAddress)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.name == null ? 0 : this.name.hashCode();
			result = result * 31 + (this.phoneNumber == null ? 0 : this.phoneNumber.hashCode());
			result = result * 31 + (this.emailAddress == null ? 0 : this.emailAddress.hashCode());
			result = result * 31 + (this.shippingAddress == null ? 0 : this.shippingAddress.hashCode());
			return result;
		}
	}

	/**
	 * The title of a page.
	**/
	public static final class PageBlockTitle extends PageBlock {


		/**
		 * Title.
		**/
		public RichText title;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1629664784;

		/**
		 * The title of a page.
		**/
		public PageBlockTitle() {}

		/**
		 * The title of a page.
		 *
		 * @param title Title.
		**/
		public PageBlockTitle(RichText title) {
			this.title = title;
		}

		/**
		 * The title of a page.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PageBlockTitle(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case RichTextPlain.CONSTRUCTOR: this.title = new RichTextPlain(input); break;
					case RichTextBold.CONSTRUCTOR: this.title = new RichTextBold(input); break;
					case RichTextItalic.CONSTRUCTOR: this.title = new RichTextItalic(input); break;
					case RichTextUnderline.CONSTRUCTOR: this.title = new RichTextUnderline(input); break;
					case RichTextStrikethrough.CONSTRUCTOR: this.title = new RichTextStrikethrough(input); break;
					case RichTextFixed.CONSTRUCTOR: this.title = new RichTextFixed(input); break;
					case RichTextUrl.CONSTRUCTOR: this.title = new RichTextUrl(input); break;
					case RichTextEmailAddress.CONSTRUCTOR: this.title = new RichTextEmailAddress(input); break;
					case RichTextSubscript.CONSTRUCTOR: this.title = new RichTextSubscript(input); break;
					case RichTextSuperscript.CONSTRUCTOR: this.title = new RichTextSuperscript(input); break;
					case RichTextMarked.CONSTRUCTOR: this.title = new RichTextMarked(input); break;
					case RichTextPhoneNumber.CONSTRUCTOR: this.title = new RichTextPhoneNumber(input); break;
					case RichTextIcon.CONSTRUCTOR: this.title = new RichTextIcon(input); break;
					case RichTextReference.CONSTRUCTOR: this.title = new RichTextReference(input); break;
					case RichTextAnchor.CONSTRUCTOR: this.title = new RichTextAnchor(input); break;
					case RichTextAnchorLink.CONSTRUCTOR: this.title = new RichTextAnchorLink(input); break;
					case RichTexts.CONSTRUCTOR: this.title = new RichTexts(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PageBlockTitle.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PageBlockTitle.CONSTRUCTOR);
			if (this.title == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.title.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PageBlockTitle pageBlockTitle = (PageBlockTitle) o;
			if (!Objects.equals(this.title, pageBlockTitle.title)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.title == null ? 0 : this.title.hashCode();
		}
	}

	/**
	 * The subtitle of a page.
	**/
	public static final class PageBlockSubtitle extends PageBlock {


		/**
		 * Subtitle.
		**/
		public RichText subtitle;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 264524263;

		/**
		 * The subtitle of a page.
		**/
		public PageBlockSubtitle() {}

		/**
		 * The subtitle of a page.
		 *
		 * @param subtitle Subtitle.
		**/
		public PageBlockSubtitle(RichText subtitle) {
			this.subtitle = subtitle;
		}

		/**
		 * The subtitle of a page.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PageBlockSubtitle(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case RichTextPlain.CONSTRUCTOR: this.subtitle = new RichTextPlain(input); break;
					case RichTextBold.CONSTRUCTOR: this.subtitle = new RichTextBold(input); break;
					case RichTextItalic.CONSTRUCTOR: this.subtitle = new RichTextItalic(input); break;
					case RichTextUnderline.CONSTRUCTOR: this.subtitle = new RichTextUnderline(input); break;
					case RichTextStrikethrough.CONSTRUCTOR: this.subtitle = new RichTextStrikethrough(input); break;
					case RichTextFixed.CONSTRUCTOR: this.subtitle = new RichTextFixed(input); break;
					case RichTextUrl.CONSTRUCTOR: this.subtitle = new RichTextUrl(input); break;
					case RichTextEmailAddress.CONSTRUCTOR: this.subtitle = new RichTextEmailAddress(input); break;
					case RichTextSubscript.CONSTRUCTOR: this.subtitle = new RichTextSubscript(input); break;
					case RichTextSuperscript.CONSTRUCTOR: this.subtitle = new RichTextSuperscript(input); break;
					case RichTextMarked.CONSTRUCTOR: this.subtitle = new RichTextMarked(input); break;
					case RichTextPhoneNumber.CONSTRUCTOR: this.subtitle = new RichTextPhoneNumber(input); break;
					case RichTextIcon.CONSTRUCTOR: this.subtitle = new RichTextIcon(input); break;
					case RichTextReference.CONSTRUCTOR: this.subtitle = new RichTextReference(input); break;
					case RichTextAnchor.CONSTRUCTOR: this.subtitle = new RichTextAnchor(input); break;
					case RichTextAnchorLink.CONSTRUCTOR: this.subtitle = new RichTextAnchorLink(input); break;
					case RichTexts.CONSTRUCTOR: this.subtitle = new RichTexts(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PageBlockSubtitle.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PageBlockSubtitle.CONSTRUCTOR);
			if (this.subtitle == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.subtitle.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PageBlockSubtitle pageBlockSubtitle = (PageBlockSubtitle) o;
			if (!Objects.equals(this.subtitle, pageBlockSubtitle.subtitle)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.subtitle == null ? 0 : this.subtitle.hashCode();
		}
	}

	/**
	 * The author and publishing date of a page.
	**/
	public static final class PageBlockAuthorDate extends PageBlock {


		/**
		 * Author.
		**/
		public RichText author;

		/**
		 * Point in time (Unix timestamp) when the article was published; 0 if unknown.
		**/
		public int publishDate;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1300231184;

		/**
		 * The author and publishing date of a page.
		**/
		public PageBlockAuthorDate() {}

		/**
		 * The author and publishing date of a page.
		 *
		 * @param author Author.
		 * @param publishDate Point in time (Unix timestamp) when the article was published; 0 if unknown.
		**/
		public PageBlockAuthorDate(RichText author, int publishDate) {
			this.author = author;
			this.publishDate = publishDate;
		}

		/**
		 * The author and publishing date of a page.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PageBlockAuthorDate(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case RichTextPlain.CONSTRUCTOR: this.author = new RichTextPlain(input); break;
					case RichTextBold.CONSTRUCTOR: this.author = new RichTextBold(input); break;
					case RichTextItalic.CONSTRUCTOR: this.author = new RichTextItalic(input); break;
					case RichTextUnderline.CONSTRUCTOR: this.author = new RichTextUnderline(input); break;
					case RichTextStrikethrough.CONSTRUCTOR: this.author = new RichTextStrikethrough(input); break;
					case RichTextFixed.CONSTRUCTOR: this.author = new RichTextFixed(input); break;
					case RichTextUrl.CONSTRUCTOR: this.author = new RichTextUrl(input); break;
					case RichTextEmailAddress.CONSTRUCTOR: this.author = new RichTextEmailAddress(input); break;
					case RichTextSubscript.CONSTRUCTOR: this.author = new RichTextSubscript(input); break;
					case RichTextSuperscript.CONSTRUCTOR: this.author = new RichTextSuperscript(input); break;
					case RichTextMarked.CONSTRUCTOR: this.author = new RichTextMarked(input); break;
					case RichTextPhoneNumber.CONSTRUCTOR: this.author = new RichTextPhoneNumber(input); break;
					case RichTextIcon.CONSTRUCTOR: this.author = new RichTextIcon(input); break;
					case RichTextReference.CONSTRUCTOR: this.author = new RichTextReference(input); break;
					case RichTextAnchor.CONSTRUCTOR: this.author = new RichTextAnchor(input); break;
					case RichTextAnchorLink.CONSTRUCTOR: this.author = new RichTextAnchorLink(input); break;
					case RichTexts.CONSTRUCTOR: this.author = new RichTexts(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.publishDate = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PageBlockAuthorDate.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PageBlockAuthorDate.CONSTRUCTOR);
			if (this.author == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.author.serialize(output);
			}
			output.writeInt(this.publishDate);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PageBlockAuthorDate pageBlockAuthorDate = (PageBlockAuthorDate) o;
			if (!Objects.equals(this.author, pageBlockAuthorDate.author)) {
				return false;
			}
			if (this.publishDate != pageBlockAuthorDate.publishDate) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.publishDate);
			result = result * 31 + (this.author == null ? 0 : this.author.hashCode());
			return result;
		}
	}

	/**
	 * A header.
	**/
	public static final class PageBlockHeader extends PageBlock {


		/**
		 * Header.
		**/
		public RichText header;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1402854811;

		/**
		 * A header.
		**/
		public PageBlockHeader() {}

		/**
		 * A header.
		 *
		 * @param header Header.
		**/
		public PageBlockHeader(RichText header) {
			this.header = header;
		}

		/**
		 * A header.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PageBlockHeader(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case RichTextPlain.CONSTRUCTOR: this.header = new RichTextPlain(input); break;
					case RichTextBold.CONSTRUCTOR: this.header = new RichTextBold(input); break;
					case RichTextItalic.CONSTRUCTOR: this.header = new RichTextItalic(input); break;
					case RichTextUnderline.CONSTRUCTOR: this.header = new RichTextUnderline(input); break;
					case RichTextStrikethrough.CONSTRUCTOR: this.header = new RichTextStrikethrough(input); break;
					case RichTextFixed.CONSTRUCTOR: this.header = new RichTextFixed(input); break;
					case RichTextUrl.CONSTRUCTOR: this.header = new RichTextUrl(input); break;
					case RichTextEmailAddress.CONSTRUCTOR: this.header = new RichTextEmailAddress(input); break;
					case RichTextSubscript.CONSTRUCTOR: this.header = new RichTextSubscript(input); break;
					case RichTextSuperscript.CONSTRUCTOR: this.header = new RichTextSuperscript(input); break;
					case RichTextMarked.CONSTRUCTOR: this.header = new RichTextMarked(input); break;
					case RichTextPhoneNumber.CONSTRUCTOR: this.header = new RichTextPhoneNumber(input); break;
					case RichTextIcon.CONSTRUCTOR: this.header = new RichTextIcon(input); break;
					case RichTextReference.CONSTRUCTOR: this.header = new RichTextReference(input); break;
					case RichTextAnchor.CONSTRUCTOR: this.header = new RichTextAnchor(input); break;
					case RichTextAnchorLink.CONSTRUCTOR: this.header = new RichTextAnchorLink(input); break;
					case RichTexts.CONSTRUCTOR: this.header = new RichTexts(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PageBlockHeader.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PageBlockHeader.CONSTRUCTOR);
			if (this.header == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.header.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PageBlockHeader pageBlockHeader = (PageBlockHeader) o;
			if (!Objects.equals(this.header, pageBlockHeader.header)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.header == null ? 0 : this.header.hashCode();
		}
	}

	/**
	 * A subheader.
	**/
	public static final class PageBlockSubheader extends PageBlock {


		/**
		 * Subheader.
		**/
		public RichText subheader;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1263956774;

		/**
		 * A subheader.
		**/
		public PageBlockSubheader() {}

		/**
		 * A subheader.
		 *
		 * @param subheader Subheader.
		**/
		public PageBlockSubheader(RichText subheader) {
			this.subheader = subheader;
		}

		/**
		 * A subheader.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PageBlockSubheader(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case RichTextPlain.CONSTRUCTOR: this.subheader = new RichTextPlain(input); break;
					case RichTextBold.CONSTRUCTOR: this.subheader = new RichTextBold(input); break;
					case RichTextItalic.CONSTRUCTOR: this.subheader = new RichTextItalic(input); break;
					case RichTextUnderline.CONSTRUCTOR: this.subheader = new RichTextUnderline(input); break;
					case RichTextStrikethrough.CONSTRUCTOR: this.subheader = new RichTextStrikethrough(input); break;
					case RichTextFixed.CONSTRUCTOR: this.subheader = new RichTextFixed(input); break;
					case RichTextUrl.CONSTRUCTOR: this.subheader = new RichTextUrl(input); break;
					case RichTextEmailAddress.CONSTRUCTOR: this.subheader = new RichTextEmailAddress(input); break;
					case RichTextSubscript.CONSTRUCTOR: this.subheader = new RichTextSubscript(input); break;
					case RichTextSuperscript.CONSTRUCTOR: this.subheader = new RichTextSuperscript(input); break;
					case RichTextMarked.CONSTRUCTOR: this.subheader = new RichTextMarked(input); break;
					case RichTextPhoneNumber.CONSTRUCTOR: this.subheader = new RichTextPhoneNumber(input); break;
					case RichTextIcon.CONSTRUCTOR: this.subheader = new RichTextIcon(input); break;
					case RichTextReference.CONSTRUCTOR: this.subheader = new RichTextReference(input); break;
					case RichTextAnchor.CONSTRUCTOR: this.subheader = new RichTextAnchor(input); break;
					case RichTextAnchorLink.CONSTRUCTOR: this.subheader = new RichTextAnchorLink(input); break;
					case RichTexts.CONSTRUCTOR: this.subheader = new RichTexts(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PageBlockSubheader.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PageBlockSubheader.CONSTRUCTOR);
			if (this.subheader == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.subheader.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PageBlockSubheader pageBlockSubheader = (PageBlockSubheader) o;
			if (!Objects.equals(this.subheader, pageBlockSubheader.subheader)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.subheader == null ? 0 : this.subheader.hashCode();
		}
	}

	/**
	 * A kicker.
	**/
	public static final class PageBlockKicker extends PageBlock {


		/**
		 * Kicker.
		**/
		public RichText kicker;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1361282635;

		/**
		 * A kicker.
		**/
		public PageBlockKicker() {}

		/**
		 * A kicker.
		 *
		 * @param kicker Kicker.
		**/
		public PageBlockKicker(RichText kicker) {
			this.kicker = kicker;
		}

		/**
		 * A kicker.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PageBlockKicker(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case RichTextPlain.CONSTRUCTOR: this.kicker = new RichTextPlain(input); break;
					case RichTextBold.CONSTRUCTOR: this.kicker = new RichTextBold(input); break;
					case RichTextItalic.CONSTRUCTOR: this.kicker = new RichTextItalic(input); break;
					case RichTextUnderline.CONSTRUCTOR: this.kicker = new RichTextUnderline(input); break;
					case RichTextStrikethrough.CONSTRUCTOR: this.kicker = new RichTextStrikethrough(input); break;
					case RichTextFixed.CONSTRUCTOR: this.kicker = new RichTextFixed(input); break;
					case RichTextUrl.CONSTRUCTOR: this.kicker = new RichTextUrl(input); break;
					case RichTextEmailAddress.CONSTRUCTOR: this.kicker = new RichTextEmailAddress(input); break;
					case RichTextSubscript.CONSTRUCTOR: this.kicker = new RichTextSubscript(input); break;
					case RichTextSuperscript.CONSTRUCTOR: this.kicker = new RichTextSuperscript(input); break;
					case RichTextMarked.CONSTRUCTOR: this.kicker = new RichTextMarked(input); break;
					case RichTextPhoneNumber.CONSTRUCTOR: this.kicker = new RichTextPhoneNumber(input); break;
					case RichTextIcon.CONSTRUCTOR: this.kicker = new RichTextIcon(input); break;
					case RichTextReference.CONSTRUCTOR: this.kicker = new RichTextReference(input); break;
					case RichTextAnchor.CONSTRUCTOR: this.kicker = new RichTextAnchor(input); break;
					case RichTextAnchorLink.CONSTRUCTOR: this.kicker = new RichTextAnchorLink(input); break;
					case RichTexts.CONSTRUCTOR: this.kicker = new RichTexts(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PageBlockKicker.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PageBlockKicker.CONSTRUCTOR);
			if (this.kicker == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.kicker.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PageBlockKicker pageBlockKicker = (PageBlockKicker) o;
			if (!Objects.equals(this.kicker, pageBlockKicker.kicker)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.kicker == null ? 0 : this.kicker.hashCode();
		}
	}

	/**
	 * A text paragraph.
	**/
	public static final class PageBlockParagraph extends PageBlock {


		/**
		 * Paragraph text.
		**/
		public RichText text;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1182402406;

		/**
		 * A text paragraph.
		**/
		public PageBlockParagraph() {}

		/**
		 * A text paragraph.
		 *
		 * @param text Paragraph text.
		**/
		public PageBlockParagraph(RichText text) {
			this.text = text;
		}

		/**
		 * A text paragraph.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PageBlockParagraph(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case RichTextPlain.CONSTRUCTOR: this.text = new RichTextPlain(input); break;
					case RichTextBold.CONSTRUCTOR: this.text = new RichTextBold(input); break;
					case RichTextItalic.CONSTRUCTOR: this.text = new RichTextItalic(input); break;
					case RichTextUnderline.CONSTRUCTOR: this.text = new RichTextUnderline(input); break;
					case RichTextStrikethrough.CONSTRUCTOR: this.text = new RichTextStrikethrough(input); break;
					case RichTextFixed.CONSTRUCTOR: this.text = new RichTextFixed(input); break;
					case RichTextUrl.CONSTRUCTOR: this.text = new RichTextUrl(input); break;
					case RichTextEmailAddress.CONSTRUCTOR: this.text = new RichTextEmailAddress(input); break;
					case RichTextSubscript.CONSTRUCTOR: this.text = new RichTextSubscript(input); break;
					case RichTextSuperscript.CONSTRUCTOR: this.text = new RichTextSuperscript(input); break;
					case RichTextMarked.CONSTRUCTOR: this.text = new RichTextMarked(input); break;
					case RichTextPhoneNumber.CONSTRUCTOR: this.text = new RichTextPhoneNumber(input); break;
					case RichTextIcon.CONSTRUCTOR: this.text = new RichTextIcon(input); break;
					case RichTextReference.CONSTRUCTOR: this.text = new RichTextReference(input); break;
					case RichTextAnchor.CONSTRUCTOR: this.text = new RichTextAnchor(input); break;
					case RichTextAnchorLink.CONSTRUCTOR: this.text = new RichTextAnchorLink(input); break;
					case RichTexts.CONSTRUCTOR: this.text = new RichTexts(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PageBlockParagraph.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PageBlockParagraph.CONSTRUCTOR);
			if (this.text == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.text.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PageBlockParagraph pageBlockParagraph = (PageBlockParagraph) o;
			if (!Objects.equals(this.text, pageBlockParagraph.text)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.text == null ? 0 : this.text.hashCode();
		}
	}

	/**
	 * A preformatted text paragraph.
	**/
	public static final class PageBlockPreformatted extends PageBlock {


		/**
		 * Paragraph text.
		**/
		public RichText text;

		/**
		 * Programming language for which the text needs to be formatted.
		**/
		public String language;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1066346178;

		/**
		 * A preformatted text paragraph.
		**/
		public PageBlockPreformatted() {}

		/**
		 * A preformatted text paragraph.
		 *
		 * @param text Paragraph text.
		 * @param language Programming language for which the text needs to be formatted.
		**/
		public PageBlockPreformatted(RichText text, String language) {
			this.text = text;
			this.language = language;
		}

		/**
		 * A preformatted text paragraph.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PageBlockPreformatted(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case RichTextPlain.CONSTRUCTOR: this.text = new RichTextPlain(input); break;
					case RichTextBold.CONSTRUCTOR: this.text = new RichTextBold(input); break;
					case RichTextItalic.CONSTRUCTOR: this.text = new RichTextItalic(input); break;
					case RichTextUnderline.CONSTRUCTOR: this.text = new RichTextUnderline(input); break;
					case RichTextStrikethrough.CONSTRUCTOR: this.text = new RichTextStrikethrough(input); break;
					case RichTextFixed.CONSTRUCTOR: this.text = new RichTextFixed(input); break;
					case RichTextUrl.CONSTRUCTOR: this.text = new RichTextUrl(input); break;
					case RichTextEmailAddress.CONSTRUCTOR: this.text = new RichTextEmailAddress(input); break;
					case RichTextSubscript.CONSTRUCTOR: this.text = new RichTextSubscript(input); break;
					case RichTextSuperscript.CONSTRUCTOR: this.text = new RichTextSuperscript(input); break;
					case RichTextMarked.CONSTRUCTOR: this.text = new RichTextMarked(input); break;
					case RichTextPhoneNumber.CONSTRUCTOR: this.text = new RichTextPhoneNumber(input); break;
					case RichTextIcon.CONSTRUCTOR: this.text = new RichTextIcon(input); break;
					case RichTextReference.CONSTRUCTOR: this.text = new RichTextReference(input); break;
					case RichTextAnchor.CONSTRUCTOR: this.text = new RichTextAnchor(input); break;
					case RichTextAnchorLink.CONSTRUCTOR: this.text = new RichTextAnchorLink(input); break;
					case RichTexts.CONSTRUCTOR: this.text = new RichTexts(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				byte[] languageTmp = new byte[input.readInt()];
				input.readFully(languageTmp);
				this.language = new String(languageTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PageBlockPreformatted.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PageBlockPreformatted.CONSTRUCTOR);
			if (this.text == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.text.serialize(output);
			}
			if (this.language == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] languageTmp = this.language.getBytes(StandardCharsets.UTF_8);
				output.writeInt(languageTmp.length);
				output.write(languageTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PageBlockPreformatted pageBlockPreformatted = (PageBlockPreformatted) o;
			if (!Objects.equals(this.text, pageBlockPreformatted.text)) {
				return false;
			}
			if (this.language != pageBlockPreformatted.language) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.text == null ? 0 : this.text.hashCode();
			result = result * 31 + (this.language == null ? 0 : this.language.hashCode());
			return result;
		}
	}

	/**
	 * The footer of a page.
	**/
	public static final class PageBlockFooter extends PageBlock {


		/**
		 * Footer.
		**/
		public RichText footer;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 886429480;

		/**
		 * The footer of a page.
		**/
		public PageBlockFooter() {}

		/**
		 * The footer of a page.
		 *
		 * @param footer Footer.
		**/
		public PageBlockFooter(RichText footer) {
			this.footer = footer;
		}

		/**
		 * The footer of a page.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PageBlockFooter(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case RichTextPlain.CONSTRUCTOR: this.footer = new RichTextPlain(input); break;
					case RichTextBold.CONSTRUCTOR: this.footer = new RichTextBold(input); break;
					case RichTextItalic.CONSTRUCTOR: this.footer = new RichTextItalic(input); break;
					case RichTextUnderline.CONSTRUCTOR: this.footer = new RichTextUnderline(input); break;
					case RichTextStrikethrough.CONSTRUCTOR: this.footer = new RichTextStrikethrough(input); break;
					case RichTextFixed.CONSTRUCTOR: this.footer = new RichTextFixed(input); break;
					case RichTextUrl.CONSTRUCTOR: this.footer = new RichTextUrl(input); break;
					case RichTextEmailAddress.CONSTRUCTOR: this.footer = new RichTextEmailAddress(input); break;
					case RichTextSubscript.CONSTRUCTOR: this.footer = new RichTextSubscript(input); break;
					case RichTextSuperscript.CONSTRUCTOR: this.footer = new RichTextSuperscript(input); break;
					case RichTextMarked.CONSTRUCTOR: this.footer = new RichTextMarked(input); break;
					case RichTextPhoneNumber.CONSTRUCTOR: this.footer = new RichTextPhoneNumber(input); break;
					case RichTextIcon.CONSTRUCTOR: this.footer = new RichTextIcon(input); break;
					case RichTextReference.CONSTRUCTOR: this.footer = new RichTextReference(input); break;
					case RichTextAnchor.CONSTRUCTOR: this.footer = new RichTextAnchor(input); break;
					case RichTextAnchorLink.CONSTRUCTOR: this.footer = new RichTextAnchorLink(input); break;
					case RichTexts.CONSTRUCTOR: this.footer = new RichTexts(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PageBlockFooter.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PageBlockFooter.CONSTRUCTOR);
			if (this.footer == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.footer.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PageBlockFooter pageBlockFooter = (PageBlockFooter) o;
			if (!Objects.equals(this.footer, pageBlockFooter.footer)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.footer == null ? 0 : this.footer.hashCode();
		}
	}

	/**
	 * An empty block separating a page.
	**/
	public static final class PageBlockDivider extends PageBlock {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -618614392;

		/**
		 * An empty block separating a page.
		**/
		public PageBlockDivider() {}

		/**
		 * An empty block separating a page.
		 *
		**/

		/**
		 * An empty block separating a page.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PageBlockDivider(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PageBlockDivider.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PageBlockDivider.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PageBlockDivider.CONSTRUCTOR;
		}
	}

	/**
	 * An invisible anchor on a page, which can be used in a URL to open the
	 * page from the specified anchor.
	**/
	public static final class PageBlockAnchor extends PageBlock {


		/**
		 * Name of the anchor.
		**/
		public String name;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -837994576;

		/**
		 * An invisible anchor on a page, which can be used in a URL to open the page from the specified anchor.
		**/
		public PageBlockAnchor() {}

		/**
		 * An invisible anchor on a page, which can be used in a URL to open the page from the specified anchor.
		 *
		 * @param name Name of the anchor.
		**/
		public PageBlockAnchor(String name) {
			this.name = name;
		}

		/**
		 * An invisible anchor on a page, which can be used in a URL to open the page from the specified anchor.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PageBlockAnchor(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] nameTmp = new byte[input.readInt()];
				input.readFully(nameTmp);
				this.name = new String(nameTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PageBlockAnchor.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PageBlockAnchor.CONSTRUCTOR);
			if (this.name == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nameTmp = this.name.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nameTmp.length);
				output.write(nameTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PageBlockAnchor pageBlockAnchor = (PageBlockAnchor) o;
			if (this.name != pageBlockAnchor.name) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.name == null ? 0 : this.name.hashCode();
		}
	}

	/**
	 * A list of data blocks.
	**/
	public static final class PageBlockList extends PageBlock {


		/**
		 * The items of the list.
		**/
		public PageBlockListItem[] items;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1037074852;

		/**
		 * A list of data blocks.
		**/
		public PageBlockList() {}

		/**
		 * A list of data blocks.
		 *
		 * @param items The items of the list.
		**/
		public PageBlockList(PageBlockListItem[] items) {
			this.items = items;
		}

		/**
		 * A list of data blocks.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PageBlockList(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.items = new PageBlockListItem[input.readInt()];
				for (int i = 0; i < this.items.length; i++) {
					if (PageBlockListItem.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.items[i] = new PageBlockListItem(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PageBlockList.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PageBlockList.CONSTRUCTOR);
			if (this.items == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.items.length);
				for (int i = 0; i < this.items.length; i++) {
					this.items[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PageBlockList pageBlockList = (PageBlockList) o;
			if (!Arrays.equals(this.items, pageBlockList.items)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.items);
		}
	}

	/**
	 * A block quote.
	**/
	public static final class PageBlockBlockQuote extends PageBlock {


		/**
		 * Quote text.
		**/
		public RichText text;

		/**
		 * Quote credit.
		**/
		public RichText credit;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1657834142;

		/**
		 * A block quote.
		**/
		public PageBlockBlockQuote() {}

		/**
		 * A block quote.
		 *
		 * @param text Quote text.
		 * @param credit Quote credit.
		**/
		public PageBlockBlockQuote(RichText text, RichText credit) {
			this.text = text;
			this.credit = credit;
		}

		/**
		 * A block quote.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PageBlockBlockQuote(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case RichTextPlain.CONSTRUCTOR: this.text = new RichTextPlain(input); break;
					case RichTextBold.CONSTRUCTOR: this.text = new RichTextBold(input); break;
					case RichTextItalic.CONSTRUCTOR: this.text = new RichTextItalic(input); break;
					case RichTextUnderline.CONSTRUCTOR: this.text = new RichTextUnderline(input); break;
					case RichTextStrikethrough.CONSTRUCTOR: this.text = new RichTextStrikethrough(input); break;
					case RichTextFixed.CONSTRUCTOR: this.text = new RichTextFixed(input); break;
					case RichTextUrl.CONSTRUCTOR: this.text = new RichTextUrl(input); break;
					case RichTextEmailAddress.CONSTRUCTOR: this.text = new RichTextEmailAddress(input); break;
					case RichTextSubscript.CONSTRUCTOR: this.text = new RichTextSubscript(input); break;
					case RichTextSuperscript.CONSTRUCTOR: this.text = new RichTextSuperscript(input); break;
					case RichTextMarked.CONSTRUCTOR: this.text = new RichTextMarked(input); break;
					case RichTextPhoneNumber.CONSTRUCTOR: this.text = new RichTextPhoneNumber(input); break;
					case RichTextIcon.CONSTRUCTOR: this.text = new RichTextIcon(input); break;
					case RichTextReference.CONSTRUCTOR: this.text = new RichTextReference(input); break;
					case RichTextAnchor.CONSTRUCTOR: this.text = new RichTextAnchor(input); break;
					case RichTextAnchorLink.CONSTRUCTOR: this.text = new RichTextAnchorLink(input); break;
					case RichTexts.CONSTRUCTOR: this.text = new RichTexts(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case RichTextPlain.CONSTRUCTOR: this.credit = new RichTextPlain(input); break;
					case RichTextBold.CONSTRUCTOR: this.credit = new RichTextBold(input); break;
					case RichTextItalic.CONSTRUCTOR: this.credit = new RichTextItalic(input); break;
					case RichTextUnderline.CONSTRUCTOR: this.credit = new RichTextUnderline(input); break;
					case RichTextStrikethrough.CONSTRUCTOR: this.credit = new RichTextStrikethrough(input); break;
					case RichTextFixed.CONSTRUCTOR: this.credit = new RichTextFixed(input); break;
					case RichTextUrl.CONSTRUCTOR: this.credit = new RichTextUrl(input); break;
					case RichTextEmailAddress.CONSTRUCTOR: this.credit = new RichTextEmailAddress(input); break;
					case RichTextSubscript.CONSTRUCTOR: this.credit = new RichTextSubscript(input); break;
					case RichTextSuperscript.CONSTRUCTOR: this.credit = new RichTextSuperscript(input); break;
					case RichTextMarked.CONSTRUCTOR: this.credit = new RichTextMarked(input); break;
					case RichTextPhoneNumber.CONSTRUCTOR: this.credit = new RichTextPhoneNumber(input); break;
					case RichTextIcon.CONSTRUCTOR: this.credit = new RichTextIcon(input); break;
					case RichTextReference.CONSTRUCTOR: this.credit = new RichTextReference(input); break;
					case RichTextAnchor.CONSTRUCTOR: this.credit = new RichTextAnchor(input); break;
					case RichTextAnchorLink.CONSTRUCTOR: this.credit = new RichTextAnchorLink(input); break;
					case RichTexts.CONSTRUCTOR: this.credit = new RichTexts(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PageBlockBlockQuote.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PageBlockBlockQuote.CONSTRUCTOR);
			if (this.text == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.text.serialize(output);
			}
			if (this.credit == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.credit.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PageBlockBlockQuote pageBlockBlockQuote = (PageBlockBlockQuote) o;
			if (!Objects.equals(this.text, pageBlockBlockQuote.text)) {
				return false;
			}
			if (!Objects.equals(this.credit, pageBlockBlockQuote.credit)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.text == null ? 0 : this.text.hashCode();
			result = result * 31 + (this.credit == null ? 0 : this.credit.hashCode());
			return result;
		}
	}

	/**
	 * A pull quote.
	**/
	public static final class PageBlockPullQuote extends PageBlock {


		/**
		 * Quote text.
		**/
		public RichText text;

		/**
		 * Quote credit.
		**/
		public RichText credit;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 490242317;

		/**
		 * A pull quote.
		**/
		public PageBlockPullQuote() {}

		/**
		 * A pull quote.
		 *
		 * @param text Quote text.
		 * @param credit Quote credit.
		**/
		public PageBlockPullQuote(RichText text, RichText credit) {
			this.text = text;
			this.credit = credit;
		}

		/**
		 * A pull quote.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PageBlockPullQuote(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case RichTextPlain.CONSTRUCTOR: this.text = new RichTextPlain(input); break;
					case RichTextBold.CONSTRUCTOR: this.text = new RichTextBold(input); break;
					case RichTextItalic.CONSTRUCTOR: this.text = new RichTextItalic(input); break;
					case RichTextUnderline.CONSTRUCTOR: this.text = new RichTextUnderline(input); break;
					case RichTextStrikethrough.CONSTRUCTOR: this.text = new RichTextStrikethrough(input); break;
					case RichTextFixed.CONSTRUCTOR: this.text = new RichTextFixed(input); break;
					case RichTextUrl.CONSTRUCTOR: this.text = new RichTextUrl(input); break;
					case RichTextEmailAddress.CONSTRUCTOR: this.text = new RichTextEmailAddress(input); break;
					case RichTextSubscript.CONSTRUCTOR: this.text = new RichTextSubscript(input); break;
					case RichTextSuperscript.CONSTRUCTOR: this.text = new RichTextSuperscript(input); break;
					case RichTextMarked.CONSTRUCTOR: this.text = new RichTextMarked(input); break;
					case RichTextPhoneNumber.CONSTRUCTOR: this.text = new RichTextPhoneNumber(input); break;
					case RichTextIcon.CONSTRUCTOR: this.text = new RichTextIcon(input); break;
					case RichTextReference.CONSTRUCTOR: this.text = new RichTextReference(input); break;
					case RichTextAnchor.CONSTRUCTOR: this.text = new RichTextAnchor(input); break;
					case RichTextAnchorLink.CONSTRUCTOR: this.text = new RichTextAnchorLink(input); break;
					case RichTexts.CONSTRUCTOR: this.text = new RichTexts(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case RichTextPlain.CONSTRUCTOR: this.credit = new RichTextPlain(input); break;
					case RichTextBold.CONSTRUCTOR: this.credit = new RichTextBold(input); break;
					case RichTextItalic.CONSTRUCTOR: this.credit = new RichTextItalic(input); break;
					case RichTextUnderline.CONSTRUCTOR: this.credit = new RichTextUnderline(input); break;
					case RichTextStrikethrough.CONSTRUCTOR: this.credit = new RichTextStrikethrough(input); break;
					case RichTextFixed.CONSTRUCTOR: this.credit = new RichTextFixed(input); break;
					case RichTextUrl.CONSTRUCTOR: this.credit = new RichTextUrl(input); break;
					case RichTextEmailAddress.CONSTRUCTOR: this.credit = new RichTextEmailAddress(input); break;
					case RichTextSubscript.CONSTRUCTOR: this.credit = new RichTextSubscript(input); break;
					case RichTextSuperscript.CONSTRUCTOR: this.credit = new RichTextSuperscript(input); break;
					case RichTextMarked.CONSTRUCTOR: this.credit = new RichTextMarked(input); break;
					case RichTextPhoneNumber.CONSTRUCTOR: this.credit = new RichTextPhoneNumber(input); break;
					case RichTextIcon.CONSTRUCTOR: this.credit = new RichTextIcon(input); break;
					case RichTextReference.CONSTRUCTOR: this.credit = new RichTextReference(input); break;
					case RichTextAnchor.CONSTRUCTOR: this.credit = new RichTextAnchor(input); break;
					case RichTextAnchorLink.CONSTRUCTOR: this.credit = new RichTextAnchorLink(input); break;
					case RichTexts.CONSTRUCTOR: this.credit = new RichTexts(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PageBlockPullQuote.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PageBlockPullQuote.CONSTRUCTOR);
			if (this.text == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.text.serialize(output);
			}
			if (this.credit == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.credit.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PageBlockPullQuote pageBlockPullQuote = (PageBlockPullQuote) o;
			if (!Objects.equals(this.text, pageBlockPullQuote.text)) {
				return false;
			}
			if (!Objects.equals(this.credit, pageBlockPullQuote.credit)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.text == null ? 0 : this.text.hashCode();
			result = result * 31 + (this.credit == null ? 0 : this.credit.hashCode());
			return result;
		}
	}

	/**
	 * An animation.
	**/
	public static final class PageBlockAnimation extends PageBlock {


		/**
		 * Animation file; may be null.
		**/
		public Animation animation;

		/**
		 * Animation caption.
		**/
		public PageBlockCaption caption;

		/**
		 * True, if the animation must be played automatically.
		**/
		public boolean needAutoplay;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1355669513;

		/**
		 * An animation.
		**/
		public PageBlockAnimation() {}

		/**
		 * An animation.
		 *
		 * @param animation Animation file; may be null.
		 * @param caption Animation caption.
		 * @param needAutoplay True, if the animation must be played automatically.
		**/
		public PageBlockAnimation(Animation animation,
				PageBlockCaption caption,
				boolean needAutoplay) {
			this.animation = animation;
			this.caption = caption;
			this.needAutoplay = needAutoplay;
		}

		/**
		 * An animation.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PageBlockAnimation(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Animation.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.animation = new Animation(input);
			}
			if (input.readBoolean()) {
				if (PageBlockCaption.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.caption = new PageBlockCaption(input);
			}
			this.needAutoplay = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PageBlockAnimation.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PageBlockAnimation.CONSTRUCTOR);
			if (this.animation == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.animation.serialize(output);
			}
			if (this.caption == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.caption.serialize(output);
			}
			output.writeBoolean(this.needAutoplay);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PageBlockAnimation pageBlockAnimation = (PageBlockAnimation) o;
			if (!Objects.equals(this.animation, pageBlockAnimation.animation)) {
				return false;
			}
			if (!Objects.equals(this.caption, pageBlockAnimation.caption)) {
				return false;
			}
			if (this.needAutoplay != pageBlockAnimation.needAutoplay) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.needAutoplay);
			result = result * 31 + (this.animation == null ? 0 : this.animation.hashCode());
			result = result * 31 + (this.caption == null ? 0 : this.caption.hashCode());
			return result;
		}
	}

	/**
	 * An audio file.
	**/
	public static final class PageBlockAudio extends PageBlock {


		/**
		 * Audio file; may be null.
		**/
		public Audio audio;

		/**
		 * Audio file caption.
		**/
		public PageBlockCaption caption;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -63371245;

		/**
		 * An audio file.
		**/
		public PageBlockAudio() {}

		/**
		 * An audio file.
		 *
		 * @param audio Audio file; may be null.
		 * @param caption Audio file caption.
		**/
		public PageBlockAudio(Audio audio, PageBlockCaption caption) {
			this.audio = audio;
			this.caption = caption;
		}

		/**
		 * An audio file.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PageBlockAudio(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Audio.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.audio = new Audio(input);
			}
			if (input.readBoolean()) {
				if (PageBlockCaption.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.caption = new PageBlockCaption(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PageBlockAudio.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PageBlockAudio.CONSTRUCTOR);
			if (this.audio == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.audio.serialize(output);
			}
			if (this.caption == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.caption.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PageBlockAudio pageBlockAudio = (PageBlockAudio) o;
			if (!Objects.equals(this.audio, pageBlockAudio.audio)) {
				return false;
			}
			if (!Objects.equals(this.caption, pageBlockAudio.caption)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.audio == null ? 0 : this.audio.hashCode();
			result = result * 31 + (this.caption == null ? 0 : this.caption.hashCode());
			return result;
		}
	}

	/**
	 * A photo.
	**/
	public static final class PageBlockPhoto extends PageBlock {


		/**
		 * Photo file; may be null.
		**/
		public Photo photo;

		/**
		 * Photo caption.
		**/
		public PageBlockCaption caption;

		/**
		 * URL that needs to be opened when the photo is clicked.
		**/
		public String url;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 417601156;

		/**
		 * A photo.
		**/
		public PageBlockPhoto() {}

		/**
		 * A photo.
		 *
		 * @param photo Photo file; may be null.
		 * @param caption Photo caption.
		 * @param url URL that needs to be opened when the photo is clicked.
		**/
		public PageBlockPhoto(Photo photo, PageBlockCaption caption, String url) {
			this.photo = photo;
			this.caption = caption;
			this.url = url;
		}

		/**
		 * A photo.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PageBlockPhoto(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Photo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.photo = new Photo(input);
			}
			if (input.readBoolean()) {
				if (PageBlockCaption.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.caption = new PageBlockCaption(input);
			}
			if (input.readBoolean()) {
				byte[] urlTmp = new byte[input.readInt()];
				input.readFully(urlTmp);
				this.url = new String(urlTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PageBlockPhoto.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PageBlockPhoto.CONSTRUCTOR);
			if (this.photo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.photo.serialize(output);
			}
			if (this.caption == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.caption.serialize(output);
			}
			if (this.url == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] urlTmp = this.url.getBytes(StandardCharsets.UTF_8);
				output.writeInt(urlTmp.length);
				output.write(urlTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PageBlockPhoto pageBlockPhoto = (PageBlockPhoto) o;
			if (!Objects.equals(this.photo, pageBlockPhoto.photo)) {
				return false;
			}
			if (!Objects.equals(this.caption, pageBlockPhoto.caption)) {
				return false;
			}
			if (this.url != pageBlockPhoto.url) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.photo == null ? 0 : this.photo.hashCode();
			result = result * 31 + (this.caption == null ? 0 : this.caption.hashCode());
			result = result * 31 + (this.url == null ? 0 : this.url.hashCode());
			return result;
		}
	}

	/**
	 * A video.
	**/
	public static final class PageBlockVideo extends PageBlock {


		/**
		 * Video file; may be null.
		**/
		public Video video;

		/**
		 * Video caption.
		**/
		public PageBlockCaption caption;

		/**
		 * True, if the video must be played automatically.
		**/
		public boolean needAutoplay;

		/**
		 * True, if the video must be looped.
		**/
		public boolean isLooped;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 510041394;

		/**
		 * A video.
		**/
		public PageBlockVideo() {}

		/**
		 * A video.
		 *
		 * @param video Video file; may be null.
		 * @param caption Video caption.
		 * @param needAutoplay True, if the video must be played automatically.
		 * @param isLooped True, if the video must be looped.
		**/
		public PageBlockVideo(Video video,
				PageBlockCaption caption,
				boolean needAutoplay,
				boolean isLooped) {
			this.video = video;
			this.caption = caption;
			this.needAutoplay = needAutoplay;
			this.isLooped = isLooped;
		}

		/**
		 * A video.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PageBlockVideo(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Video.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.video = new Video(input);
			}
			if (input.readBoolean()) {
				if (PageBlockCaption.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.caption = new PageBlockCaption(input);
			}
			this.needAutoplay = input.readBoolean();
			this.isLooped = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PageBlockVideo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PageBlockVideo.CONSTRUCTOR);
			if (this.video == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.video.serialize(output);
			}
			if (this.caption == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.caption.serialize(output);
			}
			output.writeBoolean(this.needAutoplay);
			output.writeBoolean(this.isLooped);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PageBlockVideo pageBlockVideo = (PageBlockVideo) o;
			if (!Objects.equals(this.video, pageBlockVideo.video)) {
				return false;
			}
			if (!Objects.equals(this.caption, pageBlockVideo.caption)) {
				return false;
			}
			if (this.needAutoplay != pageBlockVideo.needAutoplay) {
				return false;
			}
			if (this.isLooped != pageBlockVideo.isLooped) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.needAutoplay);
			result = result * 31 + (this.video == null ? 0 : this.video.hashCode());
			result = result * 31 + (this.caption == null ? 0 : this.caption.hashCode());
			return result;
		}
	}

	/**
	 * A voice note.
	**/
	public static final class PageBlockVoiceNote extends PageBlock {


		/**
		 * Voice note; may be null.
		**/
		public VoiceNote voiceNote;

		/**
		 * Voice note caption.
		**/
		public PageBlockCaption caption;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1823310463;

		/**
		 * A voice note.
		**/
		public PageBlockVoiceNote() {}

		/**
		 * A voice note.
		 *
		 * @param voiceNote Voice note; may be null.
		 * @param caption Voice note caption.
		**/
		public PageBlockVoiceNote(VoiceNote voiceNote, PageBlockCaption caption) {
			this.voiceNote = voiceNote;
			this.caption = caption;
		}

		/**
		 * A voice note.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PageBlockVoiceNote(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (VoiceNote.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.voiceNote = new VoiceNote(input);
			}
			if (input.readBoolean()) {
				if (PageBlockCaption.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.caption = new PageBlockCaption(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PageBlockVoiceNote.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PageBlockVoiceNote.CONSTRUCTOR);
			if (this.voiceNote == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.voiceNote.serialize(output);
			}
			if (this.caption == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.caption.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PageBlockVoiceNote pageBlockVoiceNote = (PageBlockVoiceNote) o;
			if (!Objects.equals(this.voiceNote, pageBlockVoiceNote.voiceNote)) {
				return false;
			}
			if (!Objects.equals(this.caption, pageBlockVoiceNote.caption)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.voiceNote == null ? 0 : this.voiceNote.hashCode();
			result = result * 31 + (this.caption == null ? 0 : this.caption.hashCode());
			return result;
		}
	}

	/**
	 * A page cover.
	**/
	public static final class PageBlockCover extends PageBlock {


		/**
		 * Cover.
		**/
		public PageBlock cover;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 972174080;

		/**
		 * A page cover.
		**/
		public PageBlockCover() {}

		/**
		 * A page cover.
		 *
		 * @param cover Cover.
		**/
		public PageBlockCover(PageBlock cover) {
			this.cover = cover;
		}

		/**
		 * A page cover.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PageBlockCover(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case PageBlockTitle.CONSTRUCTOR: this.cover = new PageBlockTitle(input); break;
					case PageBlockSubtitle.CONSTRUCTOR: this.cover = new PageBlockSubtitle(input); break;
					case PageBlockAuthorDate.CONSTRUCTOR: this.cover = new PageBlockAuthorDate(input); break;
					case PageBlockHeader.CONSTRUCTOR: this.cover = new PageBlockHeader(input); break;
					case PageBlockSubheader.CONSTRUCTOR: this.cover = new PageBlockSubheader(input); break;
					case PageBlockKicker.CONSTRUCTOR: this.cover = new PageBlockKicker(input); break;
					case PageBlockParagraph.CONSTRUCTOR: this.cover = new PageBlockParagraph(input); break;
					case PageBlockPreformatted.CONSTRUCTOR: this.cover = new PageBlockPreformatted(input); break;
					case PageBlockFooter.CONSTRUCTOR: this.cover = new PageBlockFooter(input); break;
					case PageBlockDivider.CONSTRUCTOR: this.cover = new PageBlockDivider(input); break;
					case PageBlockAnchor.CONSTRUCTOR: this.cover = new PageBlockAnchor(input); break;
					case PageBlockList.CONSTRUCTOR: this.cover = new PageBlockList(input); break;
					case PageBlockBlockQuote.CONSTRUCTOR: this.cover = new PageBlockBlockQuote(input); break;
					case PageBlockPullQuote.CONSTRUCTOR: this.cover = new PageBlockPullQuote(input); break;
					case PageBlockAnimation.CONSTRUCTOR: this.cover = new PageBlockAnimation(input); break;
					case PageBlockAudio.CONSTRUCTOR: this.cover = new PageBlockAudio(input); break;
					case PageBlockPhoto.CONSTRUCTOR: this.cover = new PageBlockPhoto(input); break;
					case PageBlockVideo.CONSTRUCTOR: this.cover = new PageBlockVideo(input); break;
					case PageBlockVoiceNote.CONSTRUCTOR: this.cover = new PageBlockVoiceNote(input); break;
					case PageBlockCover.CONSTRUCTOR: this.cover = new PageBlockCover(input); break;
					case PageBlockEmbedded.CONSTRUCTOR: this.cover = new PageBlockEmbedded(input); break;
					case PageBlockEmbeddedPost.CONSTRUCTOR: this.cover = new PageBlockEmbeddedPost(input); break;
					case PageBlockCollage.CONSTRUCTOR: this.cover = new PageBlockCollage(input); break;
					case PageBlockSlideshow.CONSTRUCTOR: this.cover = new PageBlockSlideshow(input); break;
					case PageBlockChatLink.CONSTRUCTOR: this.cover = new PageBlockChatLink(input); break;
					case PageBlockTable.CONSTRUCTOR: this.cover = new PageBlockTable(input); break;
					case PageBlockDetails.CONSTRUCTOR: this.cover = new PageBlockDetails(input); break;
					case PageBlockRelatedArticles.CONSTRUCTOR: this.cover = new PageBlockRelatedArticles(input); break;
					case PageBlockMap.CONSTRUCTOR: this.cover = new PageBlockMap(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PageBlockCover.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PageBlockCover.CONSTRUCTOR);
			if (this.cover == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.cover.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PageBlockCover pageBlockCover = (PageBlockCover) o;
			if (!Objects.equals(this.cover, pageBlockCover.cover)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.cover == null ? 0 : this.cover.hashCode();
		}
	}

	/**
	 * An embedded web page.
	**/
	public static final class PageBlockEmbedded extends PageBlock {


		/**
		 * Web page URL, if available.
		**/
		public String url;

		/**
		 * HTML-markup of the embedded page.
		**/
		public String html;

		/**
		 * Poster photo, if available; may be null.
		**/
		public Photo posterPhoto;

		/**
		 * Block width; 0 if unknown.
		**/
		public int width;

		/**
		 * Block height; 0 if unknown.
		**/
		public int height;

		/**
		 * Block caption.
		**/
		public PageBlockCaption caption;

		/**
		 * True, if the block must be full width.
		**/
		public boolean isFullWidth;

		/**
		 * True, if scrolling needs to be allowed.
		**/
		public boolean allowScrolling;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1942577763;

		/**
		 * An embedded web page.
		**/
		public PageBlockEmbedded() {}

		/**
		 * An embedded web page.
		 *
		 * @param url Web page URL, if available.
		 * @param html HTML-markup of the embedded page.
		 * @param posterPhoto Poster photo, if available; may be null.
		 * @param width Block width; 0 if unknown.
		 * @param height Block height; 0 if unknown.
		 * @param caption Block caption.
		 * @param isFullWidth True, if the block must be full width.
		 * @param allowScrolling True, if scrolling needs to be allowed.
		**/
		public PageBlockEmbedded(String url,
				String html,
				Photo posterPhoto,
				int width,
				int height,
				PageBlockCaption caption,
				boolean isFullWidth,
				boolean allowScrolling) {
			this.url = url;
			this.html = html;
			this.posterPhoto = posterPhoto;
			this.width = width;
			this.height = height;
			this.caption = caption;
			this.isFullWidth = isFullWidth;
			this.allowScrolling = allowScrolling;
		}

		/**
		 * An embedded web page.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PageBlockEmbedded(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] urlTmp = new byte[input.readInt()];
				input.readFully(urlTmp);
				this.url = new String(urlTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] htmlTmp = new byte[input.readInt()];
				input.readFully(htmlTmp);
				this.html = new String(htmlTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (Photo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.posterPhoto = new Photo(input);
			}
			this.width = input.readInt();
			this.height = input.readInt();
			if (input.readBoolean()) {
				if (PageBlockCaption.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.caption = new PageBlockCaption(input);
			}
			this.isFullWidth = input.readBoolean();
			this.allowScrolling = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PageBlockEmbedded.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PageBlockEmbedded.CONSTRUCTOR);
			if (this.url == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] urlTmp = this.url.getBytes(StandardCharsets.UTF_8);
				output.writeInt(urlTmp.length);
				output.write(urlTmp);
			}
			if (this.html == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] htmlTmp = this.html.getBytes(StandardCharsets.UTF_8);
				output.writeInt(htmlTmp.length);
				output.write(htmlTmp);
			}
			if (this.posterPhoto == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.posterPhoto.serialize(output);
			}
			output.writeInt(this.width);
			output.writeInt(this.height);
			if (this.caption == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.caption.serialize(output);
			}
			output.writeBoolean(this.isFullWidth);
			output.writeBoolean(this.allowScrolling);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PageBlockEmbedded pageBlockEmbedded = (PageBlockEmbedded) o;
			if (this.url != pageBlockEmbedded.url) {
				return false;
			}
			if (this.html != pageBlockEmbedded.html) {
				return false;
			}
			if (!Objects.equals(this.posterPhoto, pageBlockEmbedded.posterPhoto)) {
				return false;
			}
			if (this.width != pageBlockEmbedded.width) {
				return false;
			}
			if (this.height != pageBlockEmbedded.height) {
				return false;
			}
			if (!Objects.equals(this.caption, pageBlockEmbedded.caption)) {
				return false;
			}
			if (this.isFullWidth != pageBlockEmbedded.isFullWidth) {
				return false;
			}
			if (this.allowScrolling != pageBlockEmbedded.allowScrolling) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.width);
			result = result * 31 + (this.url == null ? 0 : this.url.hashCode());
			result = result * 31 + (this.html == null ? 0 : this.html.hashCode());
			result = result * 31 + (this.posterPhoto == null ? 0 : this.posterPhoto.hashCode());
			result = result * 31 + (this.caption == null ? 0 : this.caption.hashCode());
			return result;
		}
	}

	/**
	 * An embedded post.
	**/
	public static final class PageBlockEmbeddedPost extends PageBlock {


		/**
		 * Web page URL.
		**/
		public String url;

		/**
		 * Post author.
		**/
		public String author;

		/**
		 * Post author photo; may be null.
		**/
		public Photo authorPhoto;

		/**
		 * Point in time (Unix timestamp) when the post was created; 0 if unknown.
		**/
		public int date;

		/**
		 * Post content.
		**/
		public PageBlock[] pageBlocks;

		/**
		 * Post caption.
		**/
		public PageBlockCaption caption;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 397600949;

		/**
		 * An embedded post.
		**/
		public PageBlockEmbeddedPost() {}

		/**
		 * An embedded post.
		 *
		 * @param url Web page URL.
		 * @param author Post author.
		 * @param authorPhoto Post author photo; may be null.
		 * @param date Point in time (Unix timestamp) when the post was created; 0 if unknown.
		 * @param pageBlocks Post content.
		 * @param caption Post caption.
		**/
		public PageBlockEmbeddedPost(String url,
				String author,
				Photo authorPhoto,
				int date,
				PageBlock[] pageBlocks,
				PageBlockCaption caption) {
			this.url = url;
			this.author = author;
			this.authorPhoto = authorPhoto;
			this.date = date;
			this.pageBlocks = pageBlocks;
			this.caption = caption;
		}

		/**
		 * An embedded post.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PageBlockEmbeddedPost(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] urlTmp = new byte[input.readInt()];
				input.readFully(urlTmp);
				this.url = new String(urlTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] authorTmp = new byte[input.readInt()];
				input.readFully(authorTmp);
				this.author = new String(authorTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (Photo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.authorPhoto = new Photo(input);
			}
			this.date = input.readInt();
			if (input.readBoolean()) {
				this.pageBlocks = new PageBlock[input.readInt()];
				for (int i = 0; i < this.pageBlocks.length; i++) {
					switch(input.readInt()) {
						case PageBlockTitle.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockTitle(input); break;
						case PageBlockSubtitle.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockSubtitle(input); break;
						case PageBlockAuthorDate.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockAuthorDate(input); break;
						case PageBlockHeader.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockHeader(input); break;
						case PageBlockSubheader.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockSubheader(input); break;
						case PageBlockKicker.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockKicker(input); break;
						case PageBlockParagraph.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockParagraph(input); break;
						case PageBlockPreformatted.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockPreformatted(input); break;
						case PageBlockFooter.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockFooter(input); break;
						case PageBlockDivider.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockDivider(input); break;
						case PageBlockAnchor.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockAnchor(input); break;
						case PageBlockList.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockList(input); break;
						case PageBlockBlockQuote.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockBlockQuote(input); break;
						case PageBlockPullQuote.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockPullQuote(input); break;
						case PageBlockAnimation.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockAnimation(input); break;
						case PageBlockAudio.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockAudio(input); break;
						case PageBlockPhoto.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockPhoto(input); break;
						case PageBlockVideo.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockVideo(input); break;
						case PageBlockVoiceNote.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockVoiceNote(input); break;
						case PageBlockCover.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockCover(input); break;
						case PageBlockEmbedded.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockEmbedded(input); break;
						case PageBlockEmbeddedPost.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockEmbeddedPost(input); break;
						case PageBlockCollage.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockCollage(input); break;
						case PageBlockSlideshow.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockSlideshow(input); break;
						case PageBlockChatLink.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockChatLink(input); break;
						case PageBlockTable.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockTable(input); break;
						case PageBlockDetails.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockDetails(input); break;
						case PageBlockRelatedArticles.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockRelatedArticles(input); break;
						case PageBlockMap.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockMap(input); break;
						default: {
							throw new UnsupportedOperationException();
						}
					}
				}
			}
			if (input.readBoolean()) {
				if (PageBlockCaption.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.caption = new PageBlockCaption(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PageBlockEmbeddedPost.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PageBlockEmbeddedPost.CONSTRUCTOR);
			if (this.url == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] urlTmp = this.url.getBytes(StandardCharsets.UTF_8);
				output.writeInt(urlTmp.length);
				output.write(urlTmp);
			}
			if (this.author == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] authorTmp = this.author.getBytes(StandardCharsets.UTF_8);
				output.writeInt(authorTmp.length);
				output.write(authorTmp);
			}
			if (this.authorPhoto == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.authorPhoto.serialize(output);
			}
			output.writeInt(this.date);
			if (this.pageBlocks == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.pageBlocks.length);
				for (int i = 0; i < this.pageBlocks.length; i++) {
					this.pageBlocks[i].serialize(output);
				}
			}
			if (this.caption == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.caption.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PageBlockEmbeddedPost pageBlockEmbeddedPost = (PageBlockEmbeddedPost) o;
			if (this.url != pageBlockEmbeddedPost.url) {
				return false;
			}
			if (this.author != pageBlockEmbeddedPost.author) {
				return false;
			}
			if (!Objects.equals(this.authorPhoto, pageBlockEmbeddedPost.authorPhoto)) {
				return false;
			}
			if (this.date != pageBlockEmbeddedPost.date) {
				return false;
			}
			if (!Arrays.equals(this.pageBlocks, pageBlockEmbeddedPost.pageBlocks)) {
				return false;
			}
			if (!Objects.equals(this.caption, pageBlockEmbeddedPost.caption)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.date);
			result = result * 31 + (this.url == null ? 0 : this.url.hashCode());
			result = result * 31 + (this.author == null ? 0 : this.author.hashCode());
			result = result * 31 + (this.authorPhoto == null ? 0 : this.authorPhoto.hashCode());
			result = result * 31 + (Arrays.hashCode(this.pageBlocks));
			result = result * 31 + (this.caption == null ? 0 : this.caption.hashCode());
			return result;
		}
	}

	/**
	 * A collage.
	**/
	public static final class PageBlockCollage extends PageBlock {


		/**
		 * Collage item contents.
		**/
		public PageBlock[] pageBlocks;

		/**
		 * Block caption.
		**/
		public PageBlockCaption caption;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1163760110;

		/**
		 * A collage.
		**/
		public PageBlockCollage() {}

		/**
		 * A collage.
		 *
		 * @param pageBlocks Collage item contents.
		 * @param caption Block caption.
		**/
		public PageBlockCollage(PageBlock[] pageBlocks, PageBlockCaption caption) {
			this.pageBlocks = pageBlocks;
			this.caption = caption;
		}

		/**
		 * A collage.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PageBlockCollage(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.pageBlocks = new PageBlock[input.readInt()];
				for (int i = 0; i < this.pageBlocks.length; i++) {
					switch(input.readInt()) {
						case PageBlockTitle.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockTitle(input); break;
						case PageBlockSubtitle.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockSubtitle(input); break;
						case PageBlockAuthorDate.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockAuthorDate(input); break;
						case PageBlockHeader.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockHeader(input); break;
						case PageBlockSubheader.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockSubheader(input); break;
						case PageBlockKicker.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockKicker(input); break;
						case PageBlockParagraph.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockParagraph(input); break;
						case PageBlockPreformatted.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockPreformatted(input); break;
						case PageBlockFooter.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockFooter(input); break;
						case PageBlockDivider.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockDivider(input); break;
						case PageBlockAnchor.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockAnchor(input); break;
						case PageBlockList.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockList(input); break;
						case PageBlockBlockQuote.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockBlockQuote(input); break;
						case PageBlockPullQuote.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockPullQuote(input); break;
						case PageBlockAnimation.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockAnimation(input); break;
						case PageBlockAudio.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockAudio(input); break;
						case PageBlockPhoto.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockPhoto(input); break;
						case PageBlockVideo.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockVideo(input); break;
						case PageBlockVoiceNote.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockVoiceNote(input); break;
						case PageBlockCover.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockCover(input); break;
						case PageBlockEmbedded.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockEmbedded(input); break;
						case PageBlockEmbeddedPost.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockEmbeddedPost(input); break;
						case PageBlockCollage.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockCollage(input); break;
						case PageBlockSlideshow.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockSlideshow(input); break;
						case PageBlockChatLink.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockChatLink(input); break;
						case PageBlockTable.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockTable(input); break;
						case PageBlockDetails.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockDetails(input); break;
						case PageBlockRelatedArticles.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockRelatedArticles(input); break;
						case PageBlockMap.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockMap(input); break;
						default: {
							throw new UnsupportedOperationException();
						}
					}
				}
			}
			if (input.readBoolean()) {
				if (PageBlockCaption.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.caption = new PageBlockCaption(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PageBlockCollage.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PageBlockCollage.CONSTRUCTOR);
			if (this.pageBlocks == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.pageBlocks.length);
				for (int i = 0; i < this.pageBlocks.length; i++) {
					this.pageBlocks[i].serialize(output);
				}
			}
			if (this.caption == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.caption.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PageBlockCollage pageBlockCollage = (PageBlockCollage) o;
			if (!Arrays.equals(this.pageBlocks, pageBlockCollage.pageBlocks)) {
				return false;
			}
			if (!Objects.equals(this.caption, pageBlockCollage.caption)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Arrays.hashCode(this.pageBlocks);
			result = result * 31 + (this.caption == null ? 0 : this.caption.hashCode());
			return result;
		}
	}

	/**
	 * A slideshow.
	**/
	public static final class PageBlockSlideshow extends PageBlock {


		/**
		 * Slideshow item contents.
		**/
		public PageBlock[] pageBlocks;

		/**
		 * Block caption.
		**/
		public PageBlockCaption caption;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 539217375;

		/**
		 * A slideshow.
		**/
		public PageBlockSlideshow() {}

		/**
		 * A slideshow.
		 *
		 * @param pageBlocks Slideshow item contents.
		 * @param caption Block caption.
		**/
		public PageBlockSlideshow(PageBlock[] pageBlocks, PageBlockCaption caption) {
			this.pageBlocks = pageBlocks;
			this.caption = caption;
		}

		/**
		 * A slideshow.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PageBlockSlideshow(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.pageBlocks = new PageBlock[input.readInt()];
				for (int i = 0; i < this.pageBlocks.length; i++) {
					switch(input.readInt()) {
						case PageBlockTitle.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockTitle(input); break;
						case PageBlockSubtitle.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockSubtitle(input); break;
						case PageBlockAuthorDate.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockAuthorDate(input); break;
						case PageBlockHeader.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockHeader(input); break;
						case PageBlockSubheader.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockSubheader(input); break;
						case PageBlockKicker.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockKicker(input); break;
						case PageBlockParagraph.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockParagraph(input); break;
						case PageBlockPreformatted.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockPreformatted(input); break;
						case PageBlockFooter.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockFooter(input); break;
						case PageBlockDivider.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockDivider(input); break;
						case PageBlockAnchor.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockAnchor(input); break;
						case PageBlockList.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockList(input); break;
						case PageBlockBlockQuote.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockBlockQuote(input); break;
						case PageBlockPullQuote.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockPullQuote(input); break;
						case PageBlockAnimation.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockAnimation(input); break;
						case PageBlockAudio.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockAudio(input); break;
						case PageBlockPhoto.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockPhoto(input); break;
						case PageBlockVideo.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockVideo(input); break;
						case PageBlockVoiceNote.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockVoiceNote(input); break;
						case PageBlockCover.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockCover(input); break;
						case PageBlockEmbedded.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockEmbedded(input); break;
						case PageBlockEmbeddedPost.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockEmbeddedPost(input); break;
						case PageBlockCollage.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockCollage(input); break;
						case PageBlockSlideshow.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockSlideshow(input); break;
						case PageBlockChatLink.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockChatLink(input); break;
						case PageBlockTable.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockTable(input); break;
						case PageBlockDetails.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockDetails(input); break;
						case PageBlockRelatedArticles.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockRelatedArticles(input); break;
						case PageBlockMap.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockMap(input); break;
						default: {
							throw new UnsupportedOperationException();
						}
					}
				}
			}
			if (input.readBoolean()) {
				if (PageBlockCaption.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.caption = new PageBlockCaption(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PageBlockSlideshow.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PageBlockSlideshow.CONSTRUCTOR);
			if (this.pageBlocks == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.pageBlocks.length);
				for (int i = 0; i < this.pageBlocks.length; i++) {
					this.pageBlocks[i].serialize(output);
				}
			}
			if (this.caption == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.caption.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PageBlockSlideshow pageBlockSlideshow = (PageBlockSlideshow) o;
			if (!Arrays.equals(this.pageBlocks, pageBlockSlideshow.pageBlocks)) {
				return false;
			}
			if (!Objects.equals(this.caption, pageBlockSlideshow.caption)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Arrays.hashCode(this.pageBlocks);
			result = result * 31 + (this.caption == null ? 0 : this.caption.hashCode());
			return result;
		}
	}

	/**
	 * A link to a chat.
	**/
	public static final class PageBlockChatLink extends PageBlock {


		/**
		 * Chat title.
		**/
		public String title;

		/**
		 * Chat photo; may be null.
		**/
		public ChatPhotoInfo photo;

		/**
		 * Chat username by which all other information about the chat can be resolved.
		**/
		public String username;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -202091253;

		/**
		 * A link to a chat.
		**/
		public PageBlockChatLink() {}

		/**
		 * A link to a chat.
		 *
		 * @param title Chat title.
		 * @param photo Chat photo; may be null.
		 * @param username Chat username by which all other information about the chat can be resolved.
		**/
		public PageBlockChatLink(String title, ChatPhotoInfo photo, String username) {
			this.title = title;
			this.photo = photo;
			this.username = username;
		}

		/**
		 * A link to a chat.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PageBlockChatLink(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (ChatPhotoInfo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.photo = new ChatPhotoInfo(input);
			}
			if (input.readBoolean()) {
				byte[] usernameTmp = new byte[input.readInt()];
				input.readFully(usernameTmp);
				this.username = new String(usernameTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PageBlockChatLink.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PageBlockChatLink.CONSTRUCTOR);
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
			if (this.photo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.photo.serialize(output);
			}
			if (this.username == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] usernameTmp = this.username.getBytes(StandardCharsets.UTF_8);
				output.writeInt(usernameTmp.length);
				output.write(usernameTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PageBlockChatLink pageBlockChatLink = (PageBlockChatLink) o;
			if (this.title != pageBlockChatLink.title) {
				return false;
			}
			if (!Objects.equals(this.photo, pageBlockChatLink.photo)) {
				return false;
			}
			if (this.username != pageBlockChatLink.username) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.title == null ? 0 : this.title.hashCode();
			result = result * 31 + (this.photo == null ? 0 : this.photo.hashCode());
			result = result * 31 + (this.username == null ? 0 : this.username.hashCode());
			return result;
		}
	}

	/**
	 * A table.
	**/
	public static final class PageBlockTable extends PageBlock {


		/**
		 * Table caption.
		**/
		public RichText caption;

		/**
		 * Table cells.
		**/
		public PageBlockTableCell[][] cells;

		/**
		 * True, if the table is bordered.
		**/
		public boolean isBordered;

		/**
		 * True, if the table is striped.
		**/
		public boolean isStriped;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -942649288;

		/**
		 * A table.
		**/
		public PageBlockTable() {}

		/**
		 * A table.
		 *
		 * @param caption Table caption.
		 * @param cells Table cells.
		 * @param isBordered True, if the table is bordered.
		 * @param isStriped True, if the table is striped.
		**/
		public PageBlockTable(RichText caption,
				PageBlockTableCell[][] cells,
				boolean isBordered,
				boolean isStriped) {
			this.caption = caption;
			this.cells = cells;
			this.isBordered = isBordered;
			this.isStriped = isStriped;
		}

		/**
		 * A table.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PageBlockTable(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case RichTextPlain.CONSTRUCTOR: this.caption = new RichTextPlain(input); break;
					case RichTextBold.CONSTRUCTOR: this.caption = new RichTextBold(input); break;
					case RichTextItalic.CONSTRUCTOR: this.caption = new RichTextItalic(input); break;
					case RichTextUnderline.CONSTRUCTOR: this.caption = new RichTextUnderline(input); break;
					case RichTextStrikethrough.CONSTRUCTOR: this.caption = new RichTextStrikethrough(input); break;
					case RichTextFixed.CONSTRUCTOR: this.caption = new RichTextFixed(input); break;
					case RichTextUrl.CONSTRUCTOR: this.caption = new RichTextUrl(input); break;
					case RichTextEmailAddress.CONSTRUCTOR: this.caption = new RichTextEmailAddress(input); break;
					case RichTextSubscript.CONSTRUCTOR: this.caption = new RichTextSubscript(input); break;
					case RichTextSuperscript.CONSTRUCTOR: this.caption = new RichTextSuperscript(input); break;
					case RichTextMarked.CONSTRUCTOR: this.caption = new RichTextMarked(input); break;
					case RichTextPhoneNumber.CONSTRUCTOR: this.caption = new RichTextPhoneNumber(input); break;
					case RichTextIcon.CONSTRUCTOR: this.caption = new RichTextIcon(input); break;
					case RichTextReference.CONSTRUCTOR: this.caption = new RichTextReference(input); break;
					case RichTextAnchor.CONSTRUCTOR: this.caption = new RichTextAnchor(input); break;
					case RichTextAnchorLink.CONSTRUCTOR: this.caption = new RichTextAnchorLink(input); break;
					case RichTexts.CONSTRUCTOR: this.caption = new RichTexts(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				this.cells = new PageBlockTableCell[input.readInt()][];
				for (int i = 0; i < this.cells.length; i++) {
					this.cells[i] = new PageBlockTableCell[input.readInt()];					for (int j = 0; j < this.cells[i].length; j++) {
						if (PageBlockTableCell.CONSTRUCTOR != input.readInt()) {
							throw new UnsupportedOperationException();
						}
						this.cells[i][j] = new PageBlockTableCell(input);
					}
				}
			}
			this.isBordered = input.readBoolean();
			this.isStriped = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PageBlockTable.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PageBlockTable.CONSTRUCTOR);
			if (this.caption == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.caption.serialize(output);
			}
			if (this.cells == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.cells.length);
				for (int i = 0; i < this.cells.length; i++) {
					output.writeInt(this.cells[i].length);
					for (int j = 0; j < this.cells[i].length; j++) {
						this.cells[i][j].serialize(output);
					}
				}
			}
			output.writeBoolean(this.isBordered);
			output.writeBoolean(this.isStriped);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PageBlockTable pageBlockTable = (PageBlockTable) o;
			if (!Objects.equals(this.caption, pageBlockTable.caption)) {
				return false;
			}
			if (!Arrays.deepEquals(this.cells, pageBlockTable.cells)) {
				return false;
			}
			if (this.isBordered != pageBlockTable.isBordered) {
				return false;
			}
			if (this.isStriped != pageBlockTable.isStriped) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isBordered);
			result = result * 31 + (this.caption == null ? 0 : this.caption.hashCode());
			result = result * 31 + (Arrays.deepHashCode(this.cells));
			return result;
		}
	}

	/**
	 * A collapsible block.
	**/
	public static final class PageBlockDetails extends PageBlock {


		/**
		 * Always visible heading for the block.
		**/
		public RichText header;

		/**
		 * Block contents.
		**/
		public PageBlock[] pageBlocks;

		/**
		 * True, if the block is open by default.
		**/
		public boolean isOpen;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1599869809;

		/**
		 * A collapsible block.
		**/
		public PageBlockDetails() {}

		/**
		 * A collapsible block.
		 *
		 * @param header Always visible heading for the block.
		 * @param pageBlocks Block contents.
		 * @param isOpen True, if the block is open by default.
		**/
		public PageBlockDetails(RichText header, PageBlock[] pageBlocks, boolean isOpen) {
			this.header = header;
			this.pageBlocks = pageBlocks;
			this.isOpen = isOpen;
		}

		/**
		 * A collapsible block.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PageBlockDetails(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case RichTextPlain.CONSTRUCTOR: this.header = new RichTextPlain(input); break;
					case RichTextBold.CONSTRUCTOR: this.header = new RichTextBold(input); break;
					case RichTextItalic.CONSTRUCTOR: this.header = new RichTextItalic(input); break;
					case RichTextUnderline.CONSTRUCTOR: this.header = new RichTextUnderline(input); break;
					case RichTextStrikethrough.CONSTRUCTOR: this.header = new RichTextStrikethrough(input); break;
					case RichTextFixed.CONSTRUCTOR: this.header = new RichTextFixed(input); break;
					case RichTextUrl.CONSTRUCTOR: this.header = new RichTextUrl(input); break;
					case RichTextEmailAddress.CONSTRUCTOR: this.header = new RichTextEmailAddress(input); break;
					case RichTextSubscript.CONSTRUCTOR: this.header = new RichTextSubscript(input); break;
					case RichTextSuperscript.CONSTRUCTOR: this.header = new RichTextSuperscript(input); break;
					case RichTextMarked.CONSTRUCTOR: this.header = new RichTextMarked(input); break;
					case RichTextPhoneNumber.CONSTRUCTOR: this.header = new RichTextPhoneNumber(input); break;
					case RichTextIcon.CONSTRUCTOR: this.header = new RichTextIcon(input); break;
					case RichTextReference.CONSTRUCTOR: this.header = new RichTextReference(input); break;
					case RichTextAnchor.CONSTRUCTOR: this.header = new RichTextAnchor(input); break;
					case RichTextAnchorLink.CONSTRUCTOR: this.header = new RichTextAnchorLink(input); break;
					case RichTexts.CONSTRUCTOR: this.header = new RichTexts(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				this.pageBlocks = new PageBlock[input.readInt()];
				for (int i = 0; i < this.pageBlocks.length; i++) {
					switch(input.readInt()) {
						case PageBlockTitle.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockTitle(input); break;
						case PageBlockSubtitle.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockSubtitle(input); break;
						case PageBlockAuthorDate.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockAuthorDate(input); break;
						case PageBlockHeader.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockHeader(input); break;
						case PageBlockSubheader.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockSubheader(input); break;
						case PageBlockKicker.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockKicker(input); break;
						case PageBlockParagraph.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockParagraph(input); break;
						case PageBlockPreformatted.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockPreformatted(input); break;
						case PageBlockFooter.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockFooter(input); break;
						case PageBlockDivider.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockDivider(input); break;
						case PageBlockAnchor.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockAnchor(input); break;
						case PageBlockList.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockList(input); break;
						case PageBlockBlockQuote.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockBlockQuote(input); break;
						case PageBlockPullQuote.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockPullQuote(input); break;
						case PageBlockAnimation.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockAnimation(input); break;
						case PageBlockAudio.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockAudio(input); break;
						case PageBlockPhoto.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockPhoto(input); break;
						case PageBlockVideo.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockVideo(input); break;
						case PageBlockVoiceNote.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockVoiceNote(input); break;
						case PageBlockCover.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockCover(input); break;
						case PageBlockEmbedded.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockEmbedded(input); break;
						case PageBlockEmbeddedPost.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockEmbeddedPost(input); break;
						case PageBlockCollage.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockCollage(input); break;
						case PageBlockSlideshow.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockSlideshow(input); break;
						case PageBlockChatLink.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockChatLink(input); break;
						case PageBlockTable.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockTable(input); break;
						case PageBlockDetails.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockDetails(input); break;
						case PageBlockRelatedArticles.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockRelatedArticles(input); break;
						case PageBlockMap.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockMap(input); break;
						default: {
							throw new UnsupportedOperationException();
						}
					}
				}
			}
			this.isOpen = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PageBlockDetails.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PageBlockDetails.CONSTRUCTOR);
			if (this.header == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.header.serialize(output);
			}
			if (this.pageBlocks == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.pageBlocks.length);
				for (int i = 0; i < this.pageBlocks.length; i++) {
					this.pageBlocks[i].serialize(output);
				}
			}
			output.writeBoolean(this.isOpen);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PageBlockDetails pageBlockDetails = (PageBlockDetails) o;
			if (!Objects.equals(this.header, pageBlockDetails.header)) {
				return false;
			}
			if (!Arrays.equals(this.pageBlocks, pageBlockDetails.pageBlocks)) {
				return false;
			}
			if (this.isOpen != pageBlockDetails.isOpen) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isOpen);
			result = result * 31 + (this.header == null ? 0 : this.header.hashCode());
			result = result * 31 + (Arrays.hashCode(this.pageBlocks));
			return result;
		}
	}

	/**
	 * Related articles.
	**/
	public static final class PageBlockRelatedArticles extends PageBlock {


		/**
		 * Block header.
		**/
		public RichText header;

		/**
		 * List of related articles.
		**/
		public PageBlockRelatedArticle[] articles;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1807324374;

		/**
		 * Related articles.
		**/
		public PageBlockRelatedArticles() {}

		/**
		 * Related articles.
		 *
		 * @param header Block header.
		 * @param articles List of related articles.
		**/
		public PageBlockRelatedArticles(RichText header, PageBlockRelatedArticle[] articles) {
			this.header = header;
			this.articles = articles;
		}

		/**
		 * Related articles.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PageBlockRelatedArticles(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case RichTextPlain.CONSTRUCTOR: this.header = new RichTextPlain(input); break;
					case RichTextBold.CONSTRUCTOR: this.header = new RichTextBold(input); break;
					case RichTextItalic.CONSTRUCTOR: this.header = new RichTextItalic(input); break;
					case RichTextUnderline.CONSTRUCTOR: this.header = new RichTextUnderline(input); break;
					case RichTextStrikethrough.CONSTRUCTOR: this.header = new RichTextStrikethrough(input); break;
					case RichTextFixed.CONSTRUCTOR: this.header = new RichTextFixed(input); break;
					case RichTextUrl.CONSTRUCTOR: this.header = new RichTextUrl(input); break;
					case RichTextEmailAddress.CONSTRUCTOR: this.header = new RichTextEmailAddress(input); break;
					case RichTextSubscript.CONSTRUCTOR: this.header = new RichTextSubscript(input); break;
					case RichTextSuperscript.CONSTRUCTOR: this.header = new RichTextSuperscript(input); break;
					case RichTextMarked.CONSTRUCTOR: this.header = new RichTextMarked(input); break;
					case RichTextPhoneNumber.CONSTRUCTOR: this.header = new RichTextPhoneNumber(input); break;
					case RichTextIcon.CONSTRUCTOR: this.header = new RichTextIcon(input); break;
					case RichTextReference.CONSTRUCTOR: this.header = new RichTextReference(input); break;
					case RichTextAnchor.CONSTRUCTOR: this.header = new RichTextAnchor(input); break;
					case RichTextAnchorLink.CONSTRUCTOR: this.header = new RichTextAnchorLink(input); break;
					case RichTexts.CONSTRUCTOR: this.header = new RichTexts(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				this.articles = new PageBlockRelatedArticle[input.readInt()];
				for (int i = 0; i < this.articles.length; i++) {
					if (PageBlockRelatedArticle.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.articles[i] = new PageBlockRelatedArticle(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PageBlockRelatedArticles.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PageBlockRelatedArticles.CONSTRUCTOR);
			if (this.header == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.header.serialize(output);
			}
			if (this.articles == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.articles.length);
				for (int i = 0; i < this.articles.length; i++) {
					this.articles[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PageBlockRelatedArticles pageBlockRelatedArticles = (PageBlockRelatedArticles) o;
			if (!Objects.equals(this.header, pageBlockRelatedArticles.header)) {
				return false;
			}
			if (!Arrays.equals(this.articles, pageBlockRelatedArticles.articles)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.header == null ? 0 : this.header.hashCode();
			result = result * 31 + (Arrays.hashCode(this.articles));
			return result;
		}
	}

	/**
	 * A map.
	**/
	public static final class PageBlockMap extends PageBlock {


		/**
		 * Location of the map center.
		**/
		public Location location;

		/**
		 * Map zoom level.
		**/
		public int zoom;

		/**
		 * Map width.
		**/
		public int width;

		/**
		 * Map height.
		**/
		public int height;

		/**
		 * Block caption.
		**/
		public PageBlockCaption caption;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1510961171;

		/**
		 * A map.
		**/
		public PageBlockMap() {}

		/**
		 * A map.
		 *
		 * @param location Location of the map center.
		 * @param zoom Map zoom level.
		 * @param width Map width.
		 * @param height Map height.
		 * @param caption Block caption.
		**/
		public PageBlockMap(Location location,
				int zoom,
				int width,
				int height,
				PageBlockCaption caption) {
			this.location = location;
			this.zoom = zoom;
			this.width = width;
			this.height = height;
			this.caption = caption;
		}

		/**
		 * A map.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PageBlockMap(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Location.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.location = new Location(input);
			}
			this.zoom = input.readInt();
			this.width = input.readInt();
			this.height = input.readInt();
			if (input.readBoolean()) {
				if (PageBlockCaption.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.caption = new PageBlockCaption(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PageBlockMap.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PageBlockMap.CONSTRUCTOR);
			if (this.location == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.location.serialize(output);
			}
			output.writeInt(this.zoom);
			output.writeInt(this.width);
			output.writeInt(this.height);
			if (this.caption == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.caption.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PageBlockMap pageBlockMap = (PageBlockMap) o;
			if (!Objects.equals(this.location, pageBlockMap.location)) {
				return false;
			}
			if (this.zoom != pageBlockMap.zoom) {
				return false;
			}
			if (this.width != pageBlockMap.width) {
				return false;
			}
			if (this.height != pageBlockMap.height) {
				return false;
			}
			if (!Objects.equals(this.caption, pageBlockMap.caption)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.zoom);
			result = result * 31 + (this.location == null ? 0 : this.location.hashCode());
			result = result * 31 + (this.caption == null ? 0 : this.caption.hashCode());
			return result;
		}
	}

	/**
	 * Contains a caption of an instant view web page block, consisting of a
	 * text and a trailing credit.
	**/
	public static final class PageBlockCaption extends Object {


		/**
		 * Content of the caption.
		**/
		public RichText text;

		/**
		 * Block credit (like HTML tag &lt;cite&gt;).
		**/
		public RichText credit;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1180064650;

		/**
		 * Contains a caption of an instant view web page block, consisting of a text and a trailing credit.
		**/
		public PageBlockCaption() {}

		/**
		 * Contains a caption of an instant view web page block, consisting of a text and a trailing credit.
		 *
		 * @param text Content of the caption.
		 * @param credit Block credit (like HTML tag &lt;cite&gt;).
		**/
		public PageBlockCaption(RichText text, RichText credit) {
			this.text = text;
			this.credit = credit;
		}

		/**
		 * Contains a caption of an instant view web page block, consisting of a text and a trailing credit.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PageBlockCaption(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case RichTextPlain.CONSTRUCTOR: this.text = new RichTextPlain(input); break;
					case RichTextBold.CONSTRUCTOR: this.text = new RichTextBold(input); break;
					case RichTextItalic.CONSTRUCTOR: this.text = new RichTextItalic(input); break;
					case RichTextUnderline.CONSTRUCTOR: this.text = new RichTextUnderline(input); break;
					case RichTextStrikethrough.CONSTRUCTOR: this.text = new RichTextStrikethrough(input); break;
					case RichTextFixed.CONSTRUCTOR: this.text = new RichTextFixed(input); break;
					case RichTextUrl.CONSTRUCTOR: this.text = new RichTextUrl(input); break;
					case RichTextEmailAddress.CONSTRUCTOR: this.text = new RichTextEmailAddress(input); break;
					case RichTextSubscript.CONSTRUCTOR: this.text = new RichTextSubscript(input); break;
					case RichTextSuperscript.CONSTRUCTOR: this.text = new RichTextSuperscript(input); break;
					case RichTextMarked.CONSTRUCTOR: this.text = new RichTextMarked(input); break;
					case RichTextPhoneNumber.CONSTRUCTOR: this.text = new RichTextPhoneNumber(input); break;
					case RichTextIcon.CONSTRUCTOR: this.text = new RichTextIcon(input); break;
					case RichTextReference.CONSTRUCTOR: this.text = new RichTextReference(input); break;
					case RichTextAnchor.CONSTRUCTOR: this.text = new RichTextAnchor(input); break;
					case RichTextAnchorLink.CONSTRUCTOR: this.text = new RichTextAnchorLink(input); break;
					case RichTexts.CONSTRUCTOR: this.text = new RichTexts(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case RichTextPlain.CONSTRUCTOR: this.credit = new RichTextPlain(input); break;
					case RichTextBold.CONSTRUCTOR: this.credit = new RichTextBold(input); break;
					case RichTextItalic.CONSTRUCTOR: this.credit = new RichTextItalic(input); break;
					case RichTextUnderline.CONSTRUCTOR: this.credit = new RichTextUnderline(input); break;
					case RichTextStrikethrough.CONSTRUCTOR: this.credit = new RichTextStrikethrough(input); break;
					case RichTextFixed.CONSTRUCTOR: this.credit = new RichTextFixed(input); break;
					case RichTextUrl.CONSTRUCTOR: this.credit = new RichTextUrl(input); break;
					case RichTextEmailAddress.CONSTRUCTOR: this.credit = new RichTextEmailAddress(input); break;
					case RichTextSubscript.CONSTRUCTOR: this.credit = new RichTextSubscript(input); break;
					case RichTextSuperscript.CONSTRUCTOR: this.credit = new RichTextSuperscript(input); break;
					case RichTextMarked.CONSTRUCTOR: this.credit = new RichTextMarked(input); break;
					case RichTextPhoneNumber.CONSTRUCTOR: this.credit = new RichTextPhoneNumber(input); break;
					case RichTextIcon.CONSTRUCTOR: this.credit = new RichTextIcon(input); break;
					case RichTextReference.CONSTRUCTOR: this.credit = new RichTextReference(input); break;
					case RichTextAnchor.CONSTRUCTOR: this.credit = new RichTextAnchor(input); break;
					case RichTextAnchorLink.CONSTRUCTOR: this.credit = new RichTextAnchorLink(input); break;
					case RichTexts.CONSTRUCTOR: this.credit = new RichTexts(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PageBlockCaption.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PageBlockCaption.CONSTRUCTOR);
			if (this.text == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.text.serialize(output);
			}
			if (this.credit == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.credit.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PageBlockCaption pageBlockCaption = (PageBlockCaption) o;
			if (!Objects.equals(this.text, pageBlockCaption.text)) {
				return false;
			}
			if (!Objects.equals(this.credit, pageBlockCaption.credit)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.text == null ? 0 : this.text.hashCode();
			result = result * 31 + (this.credit == null ? 0 : this.credit.hashCode());
			return result;
		}
	}

	/**
	 * The content must be left-aligned.
	**/
	public static final class PageBlockHorizontalAlignmentLeft extends PageBlockHorizontalAlignment {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 848701417;

		/**
		 * The content must be left-aligned.
		**/
		public PageBlockHorizontalAlignmentLeft() {}

		/**
		 * The content must be left-aligned.
		 *
		**/

		/**
		 * The content must be left-aligned.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PageBlockHorizontalAlignmentLeft(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PageBlockHorizontalAlignmentLeft.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PageBlockHorizontalAlignmentLeft.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PageBlockHorizontalAlignmentLeft.CONSTRUCTOR;
		}
	}

	/**
	 * The content must be center-aligned.
	**/
	public static final class PageBlockHorizontalAlignmentCenter extends PageBlockHorizontalAlignment {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1009203990;

		/**
		 * The content must be center-aligned.
		**/
		public PageBlockHorizontalAlignmentCenter() {}

		/**
		 * The content must be center-aligned.
		 *
		**/

		/**
		 * The content must be center-aligned.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PageBlockHorizontalAlignmentCenter(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PageBlockHorizontalAlignmentCenter.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PageBlockHorizontalAlignmentCenter.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PageBlockHorizontalAlignmentCenter.CONSTRUCTOR;
		}
	}

	/**
	 * The content must be right-aligned.
	**/
	public static final class PageBlockHorizontalAlignmentRight extends PageBlockHorizontalAlignment {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1371369214;

		/**
		 * The content must be right-aligned.
		**/
		public PageBlockHorizontalAlignmentRight() {}

		/**
		 * The content must be right-aligned.
		 *
		**/

		/**
		 * The content must be right-aligned.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PageBlockHorizontalAlignmentRight(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PageBlockHorizontalAlignmentRight.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PageBlockHorizontalAlignmentRight.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PageBlockHorizontalAlignmentRight.CONSTRUCTOR;
		}
	}

	/**
	 * Describes an item of a list page block.
	**/
	public static final class PageBlockListItem extends Object {


		/**
		 * Item label.
		**/
		public String label;

		/**
		 * Item blocks.
		**/
		public PageBlock[] pageBlocks;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 323186259;

		/**
		 * Describes an item of a list page block.
		**/
		public PageBlockListItem() {}

		/**
		 * Describes an item of a list page block.
		 *
		 * @param label Item label.
		 * @param pageBlocks Item blocks.
		**/
		public PageBlockListItem(String label, PageBlock[] pageBlocks) {
			this.label = label;
			this.pageBlocks = pageBlocks;
		}

		/**
		 * Describes an item of a list page block.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PageBlockListItem(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] labelTmp = new byte[input.readInt()];
				input.readFully(labelTmp);
				this.label = new String(labelTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				this.pageBlocks = new PageBlock[input.readInt()];
				for (int i = 0; i < this.pageBlocks.length; i++) {
					switch(input.readInt()) {
						case PageBlockTitle.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockTitle(input); break;
						case PageBlockSubtitle.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockSubtitle(input); break;
						case PageBlockAuthorDate.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockAuthorDate(input); break;
						case PageBlockHeader.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockHeader(input); break;
						case PageBlockSubheader.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockSubheader(input); break;
						case PageBlockKicker.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockKicker(input); break;
						case PageBlockParagraph.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockParagraph(input); break;
						case PageBlockPreformatted.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockPreformatted(input); break;
						case PageBlockFooter.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockFooter(input); break;
						case PageBlockDivider.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockDivider(input); break;
						case PageBlockAnchor.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockAnchor(input); break;
						case PageBlockList.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockList(input); break;
						case PageBlockBlockQuote.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockBlockQuote(input); break;
						case PageBlockPullQuote.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockPullQuote(input); break;
						case PageBlockAnimation.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockAnimation(input); break;
						case PageBlockAudio.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockAudio(input); break;
						case PageBlockPhoto.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockPhoto(input); break;
						case PageBlockVideo.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockVideo(input); break;
						case PageBlockVoiceNote.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockVoiceNote(input); break;
						case PageBlockCover.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockCover(input); break;
						case PageBlockEmbedded.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockEmbedded(input); break;
						case PageBlockEmbeddedPost.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockEmbeddedPost(input); break;
						case PageBlockCollage.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockCollage(input); break;
						case PageBlockSlideshow.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockSlideshow(input); break;
						case PageBlockChatLink.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockChatLink(input); break;
						case PageBlockTable.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockTable(input); break;
						case PageBlockDetails.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockDetails(input); break;
						case PageBlockRelatedArticles.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockRelatedArticles(input); break;
						case PageBlockMap.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockMap(input); break;
						default: {
							throw new UnsupportedOperationException();
						}
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PageBlockListItem.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PageBlockListItem.CONSTRUCTOR);
			if (this.label == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] labelTmp = this.label.getBytes(StandardCharsets.UTF_8);
				output.writeInt(labelTmp.length);
				output.write(labelTmp);
			}
			if (this.pageBlocks == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.pageBlocks.length);
				for (int i = 0; i < this.pageBlocks.length; i++) {
					this.pageBlocks[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PageBlockListItem pageBlockListItem = (PageBlockListItem) o;
			if (this.label != pageBlockListItem.label) {
				return false;
			}
			if (!Arrays.equals(this.pageBlocks, pageBlockListItem.pageBlocks)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.label == null ? 0 : this.label.hashCode();
			result = result * 31 + (Arrays.hashCode(this.pageBlocks));
			return result;
		}
	}

	/**
	 * Contains information about a related article.
	**/
	public static final class PageBlockRelatedArticle extends Object {


		/**
		 * Related article URL.
		**/
		public String url;

		/**
		 * Article title; may be empty.
		**/
		public String title;

		/**
		 * Article description; may be empty.
		**/
		public String description;

		/**
		 * Article photo; may be null.
		**/
		public Photo photo;

		/**
		 * Article author; may be empty.
		**/
		public String author;

		/**
		 * Point in time (Unix timestamp) when the article was published; 0 if unknown.
		**/
		public int publishDate;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 481199251;

		/**
		 * Contains information about a related article.
		**/
		public PageBlockRelatedArticle() {}

		/**
		 * Contains information about a related article.
		 *
		 * @param url Related article URL.
		 * @param title Article title; may be empty.
		 * @param description Article description; may be empty.
		 * @param photo Article photo; may be null.
		 * @param author Article author; may be empty.
		 * @param publishDate Point in time (Unix timestamp) when the article was published; 0 if unknown.
		**/
		public PageBlockRelatedArticle(String url,
				String title,
				String description,
				Photo photo,
				String author,
				int publishDate) {
			this.url = url;
			this.title = title;
			this.description = description;
			this.photo = photo;
			this.author = author;
			this.publishDate = publishDate;
		}

		/**
		 * Contains information about a related article.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PageBlockRelatedArticle(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] urlTmp = new byte[input.readInt()];
				input.readFully(urlTmp);
				this.url = new String(urlTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] descriptionTmp = new byte[input.readInt()];
				input.readFully(descriptionTmp);
				this.description = new String(descriptionTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (Photo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.photo = new Photo(input);
			}
			if (input.readBoolean()) {
				byte[] authorTmp = new byte[input.readInt()];
				input.readFully(authorTmp);
				this.author = new String(authorTmp, StandardCharsets.UTF_8);
			}
			this.publishDate = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PageBlockRelatedArticle.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PageBlockRelatedArticle.CONSTRUCTOR);
			if (this.url == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] urlTmp = this.url.getBytes(StandardCharsets.UTF_8);
				output.writeInt(urlTmp.length);
				output.write(urlTmp);
			}
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
			if (this.description == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] descriptionTmp = this.description.getBytes(StandardCharsets.UTF_8);
				output.writeInt(descriptionTmp.length);
				output.write(descriptionTmp);
			}
			if (this.photo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.photo.serialize(output);
			}
			if (this.author == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] authorTmp = this.author.getBytes(StandardCharsets.UTF_8);
				output.writeInt(authorTmp.length);
				output.write(authorTmp);
			}
			output.writeInt(this.publishDate);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PageBlockRelatedArticle pageBlockRelatedArticle = (PageBlockRelatedArticle) o;
			if (this.url != pageBlockRelatedArticle.url) {
				return false;
			}
			if (this.title != pageBlockRelatedArticle.title) {
				return false;
			}
			if (this.description != pageBlockRelatedArticle.description) {
				return false;
			}
			if (!Objects.equals(this.photo, pageBlockRelatedArticle.photo)) {
				return false;
			}
			if (this.author != pageBlockRelatedArticle.author) {
				return false;
			}
			if (this.publishDate != pageBlockRelatedArticle.publishDate) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.publishDate);
			result = result * 31 + (this.url == null ? 0 : this.url.hashCode());
			result = result * 31 + (this.title == null ? 0 : this.title.hashCode());
			result = result * 31 + (this.description == null ? 0 : this.description.hashCode());
			result = result * 31 + (this.photo == null ? 0 : this.photo.hashCode());
			result = result * 31 + (this.author == null ? 0 : this.author.hashCode());
			return result;
		}
	}

	/**
	 * Represents a cell of a table.
	**/
	public static final class PageBlockTableCell extends Object {


		/**
		 * Cell text; may be null. If the text is null, then the cell must be invisible.
		**/
		public RichText text;

		/**
		 * True, if it is a header cell.
		**/
		public boolean isHeader;

		/**
		 * The number of columns the cell spans.
		**/
		public int colspan;

		/**
		 * The number of rows the cell spans.
		**/
		public int rowspan;

		/**
		 * Horizontal cell content alignment.
		**/
		public PageBlockHorizontalAlignment align;

		/**
		 * Vertical cell content alignment.
		**/
		public PageBlockVerticalAlignment valign;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1417658214;

		/**
		 * Represents a cell of a table.
		**/
		public PageBlockTableCell() {}

		/**
		 * Represents a cell of a table.
		 *
		 * @param text Cell text; may be null. If the text is null, then the cell must be invisible.
		 * @param isHeader True, if it is a header cell.
		 * @param colspan The number of columns the cell spans.
		 * @param rowspan The number of rows the cell spans.
		 * @param align Horizontal cell content alignment.
		 * @param valign Vertical cell content alignment.
		**/
		public PageBlockTableCell(RichText text,
				boolean isHeader,
				int colspan,
				int rowspan,
				PageBlockHorizontalAlignment align,
				PageBlockVerticalAlignment valign) {
			this.text = text;
			this.isHeader = isHeader;
			this.colspan = colspan;
			this.rowspan = rowspan;
			this.align = align;
			this.valign = valign;
		}

		/**
		 * Represents a cell of a table.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PageBlockTableCell(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case RichTextPlain.CONSTRUCTOR: this.text = new RichTextPlain(input); break;
					case RichTextBold.CONSTRUCTOR: this.text = new RichTextBold(input); break;
					case RichTextItalic.CONSTRUCTOR: this.text = new RichTextItalic(input); break;
					case RichTextUnderline.CONSTRUCTOR: this.text = new RichTextUnderline(input); break;
					case RichTextStrikethrough.CONSTRUCTOR: this.text = new RichTextStrikethrough(input); break;
					case RichTextFixed.CONSTRUCTOR: this.text = new RichTextFixed(input); break;
					case RichTextUrl.CONSTRUCTOR: this.text = new RichTextUrl(input); break;
					case RichTextEmailAddress.CONSTRUCTOR: this.text = new RichTextEmailAddress(input); break;
					case RichTextSubscript.CONSTRUCTOR: this.text = new RichTextSubscript(input); break;
					case RichTextSuperscript.CONSTRUCTOR: this.text = new RichTextSuperscript(input); break;
					case RichTextMarked.CONSTRUCTOR: this.text = new RichTextMarked(input); break;
					case RichTextPhoneNumber.CONSTRUCTOR: this.text = new RichTextPhoneNumber(input); break;
					case RichTextIcon.CONSTRUCTOR: this.text = new RichTextIcon(input); break;
					case RichTextReference.CONSTRUCTOR: this.text = new RichTextReference(input); break;
					case RichTextAnchor.CONSTRUCTOR: this.text = new RichTextAnchor(input); break;
					case RichTextAnchorLink.CONSTRUCTOR: this.text = new RichTextAnchorLink(input); break;
					case RichTexts.CONSTRUCTOR: this.text = new RichTexts(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.isHeader = input.readBoolean();
			this.colspan = input.readInt();
			this.rowspan = input.readInt();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case PageBlockHorizontalAlignmentLeft.CONSTRUCTOR: this.align = new PageBlockHorizontalAlignmentLeft(input); break;
					case PageBlockHorizontalAlignmentCenter.CONSTRUCTOR: this.align = new PageBlockHorizontalAlignmentCenter(input); break;
					case PageBlockHorizontalAlignmentRight.CONSTRUCTOR: this.align = new PageBlockHorizontalAlignmentRight(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case PageBlockVerticalAlignmentTop.CONSTRUCTOR: this.valign = new PageBlockVerticalAlignmentTop(input); break;
					case PageBlockVerticalAlignmentMiddle.CONSTRUCTOR: this.valign = new PageBlockVerticalAlignmentMiddle(input); break;
					case PageBlockVerticalAlignmentBottom.CONSTRUCTOR: this.valign = new PageBlockVerticalAlignmentBottom(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PageBlockTableCell.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PageBlockTableCell.CONSTRUCTOR);
			if (this.text == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.text.serialize(output);
			}
			output.writeBoolean(this.isHeader);
			output.writeInt(this.colspan);
			output.writeInt(this.rowspan);
			if (this.align == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.align.serialize(output);
			}
			if (this.valign == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.valign.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PageBlockTableCell pageBlockTableCell = (PageBlockTableCell) o;
			if (!Objects.equals(this.text, pageBlockTableCell.text)) {
				return false;
			}
			if (this.isHeader != pageBlockTableCell.isHeader) {
				return false;
			}
			if (this.colspan != pageBlockTableCell.colspan) {
				return false;
			}
			if (this.rowspan != pageBlockTableCell.rowspan) {
				return false;
			}
			if (!Objects.equals(this.align, pageBlockTableCell.align)) {
				return false;
			}
			if (!Objects.equals(this.valign, pageBlockTableCell.valign)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isHeader);
			result = result * 31 + (this.text == null ? 0 : this.text.hashCode());
			result = result * 31 + (this.align == null ? 0 : this.align.hashCode());
			result = result * 31 + (this.valign == null ? 0 : this.valign.hashCode());
			return result;
		}
	}

	/**
	 * The content must be top-aligned.
	**/
	public static final class PageBlockVerticalAlignmentTop extends PageBlockVerticalAlignment {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 195500454;

		/**
		 * The content must be top-aligned.
		**/
		public PageBlockVerticalAlignmentTop() {}

		/**
		 * The content must be top-aligned.
		 *
		**/

		/**
		 * The content must be top-aligned.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PageBlockVerticalAlignmentTop(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PageBlockVerticalAlignmentTop.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PageBlockVerticalAlignmentTop.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PageBlockVerticalAlignmentTop.CONSTRUCTOR;
		}
	}

	/**
	 * The content must be middle-aligned.
	**/
	public static final class PageBlockVerticalAlignmentMiddle extends PageBlockVerticalAlignment {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2123096587;

		/**
		 * The content must be middle-aligned.
		**/
		public PageBlockVerticalAlignmentMiddle() {}

		/**
		 * The content must be middle-aligned.
		 *
		**/

		/**
		 * The content must be middle-aligned.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PageBlockVerticalAlignmentMiddle(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PageBlockVerticalAlignmentMiddle.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PageBlockVerticalAlignmentMiddle.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PageBlockVerticalAlignmentMiddle.CONSTRUCTOR;
		}
	}

	/**
	 * The content must be bottom-aligned.
	**/
	public static final class PageBlockVerticalAlignmentBottom extends PageBlockVerticalAlignment {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2092531158;

		/**
		 * The content must be bottom-aligned.
		**/
		public PageBlockVerticalAlignmentBottom() {}

		/**
		 * The content must be bottom-aligned.
		 *
		**/

		/**
		 * The content must be bottom-aligned.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PageBlockVerticalAlignmentBottom(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PageBlockVerticalAlignmentBottom.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PageBlockVerticalAlignmentBottom.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PageBlockVerticalAlignmentBottom.CONSTRUCTOR;
		}
	}

	/**
	 * Contains information about a Telegram Passport authorization form
	 * that was requested.
	**/
	public static final class PassportAuthorizationForm extends Object {


		/**
		 * Unique identifier of the authorization form.
		**/
		public int id;

		/**
		 * Telegram Passport elements that must be provided to complete the form.
		**/
		public PassportRequiredElement[] requiredElements;

		/**
		 * URL for the privacy policy of the service; may be empty.
		**/
		public String privacyPolicyUrl;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1070673218;

		/**
		 * Contains information about a Telegram Passport authorization form that was requested.
		**/
		public PassportAuthorizationForm() {}

		/**
		 * Contains information about a Telegram Passport authorization form that was requested.
		 *
		 * @param id Unique identifier of the authorization form.
		 * @param requiredElements Telegram Passport elements that must be provided to complete the form.
		 * @param privacyPolicyUrl URL for the privacy policy of the service; may be empty.
		**/
		public PassportAuthorizationForm(int id,
				PassportRequiredElement[] requiredElements,
				String privacyPolicyUrl) {
			this.id = id;
			this.requiredElements = requiredElements;
			this.privacyPolicyUrl = privacyPolicyUrl;
		}

		/**
		 * Contains information about a Telegram Passport authorization form that was requested.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PassportAuthorizationForm(DataInput input) throws IOException {
			this.id = input.readInt();
			if (input.readBoolean()) {
				this.requiredElements = new PassportRequiredElement[input.readInt()];
				for (int i = 0; i < this.requiredElements.length; i++) {
					if (PassportRequiredElement.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.requiredElements[i] = new PassportRequiredElement(input);
				}
			}
			if (input.readBoolean()) {
				byte[] privacyPolicyUrlTmp = new byte[input.readInt()];
				input.readFully(privacyPolicyUrlTmp);
				this.privacyPolicyUrl = new String(privacyPolicyUrlTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PassportAuthorizationForm.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PassportAuthorizationForm.CONSTRUCTOR);
			output.writeInt(this.id);
			if (this.requiredElements == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.requiredElements.length);
				for (int i = 0; i < this.requiredElements.length; i++) {
					this.requiredElements[i].serialize(output);
				}
			}
			if (this.privacyPolicyUrl == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] privacyPolicyUrlTmp = this.privacyPolicyUrl.getBytes(StandardCharsets.UTF_8);
				output.writeInt(privacyPolicyUrlTmp.length);
				output.write(privacyPolicyUrlTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PassportAuthorizationForm passportAuthorizationForm = (PassportAuthorizationForm) o;
			if (this.id != passportAuthorizationForm.id) {
				return false;
			}
			if (!Arrays.equals(this.requiredElements, passportAuthorizationForm.requiredElements)) {
				return false;
			}
			if (this.privacyPolicyUrl != passportAuthorizationForm.privacyPolicyUrl) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.id);
			result = result * 31 + (Arrays.hashCode(this.requiredElements));
			result = result * 31 + (this.privacyPolicyUrl == null ? 0 : this.privacyPolicyUrl.hashCode());
			return result;
		}
	}

	/**
	 * A Telegram Passport element containing the user&#039;s personal
	 * details.
	**/
	public static final class PassportElementPersonalDetails extends PassportElement {


		/**
		 * Personal details of the user.
		**/
		public PersonalDetails personalDetails;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1217724035;

		/**
		 * A Telegram Passport element containing the user&#039;s personal details.
		**/
		public PassportElementPersonalDetails() {}

		/**
		 * A Telegram Passport element containing the user&#039;s personal details.
		 *
		 * @param personalDetails Personal details of the user.
		**/
		public PassportElementPersonalDetails(PersonalDetails personalDetails) {
			this.personalDetails = personalDetails;
		}

		/**
		 * A Telegram Passport element containing the user&#039;s personal details.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PassportElementPersonalDetails(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (PersonalDetails.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.personalDetails = new PersonalDetails(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PassportElementPersonalDetails.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PassportElementPersonalDetails.CONSTRUCTOR);
			if (this.personalDetails == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.personalDetails.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PassportElementPersonalDetails passportElementPersonalDetails = (PassportElementPersonalDetails) o;
			if (!Objects.equals(this.personalDetails, passportElementPersonalDetails.personalDetails)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.personalDetails == null ? 0 : this.personalDetails.hashCode();
		}
	}

	/**
	 * A Telegram Passport element containing the user&#039;s passport.
	**/
	public static final class PassportElementPassport extends PassportElement {


		/**
		 * Passport.
		**/
		public IdentityDocument passport;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -263985373;

		/**
		 * A Telegram Passport element containing the user&#039;s passport.
		**/
		public PassportElementPassport() {}

		/**
		 * A Telegram Passport element containing the user&#039;s passport.
		 *
		 * @param passport Passport.
		**/
		public PassportElementPassport(IdentityDocument passport) {
			this.passport = passport;
		}

		/**
		 * A Telegram Passport element containing the user&#039;s passport.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PassportElementPassport(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (IdentityDocument.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.passport = new IdentityDocument(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PassportElementPassport.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PassportElementPassport.CONSTRUCTOR);
			if (this.passport == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.passport.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PassportElementPassport passportElementPassport = (PassportElementPassport) o;
			if (!Objects.equals(this.passport, passportElementPassport.passport)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.passport == null ? 0 : this.passport.hashCode();
		}
	}

	/**
	 * A Telegram Passport element containing the user&#039;s driver license.
	**/
	public static final class PassportElementDriverLicense extends PassportElement {


		/**
		 * Driver license.
		**/
		public IdentityDocument driverLicense;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1643580589;

		/**
		 * A Telegram Passport element containing the user&#039;s driver license.
		**/
		public PassportElementDriverLicense() {}

		/**
		 * A Telegram Passport element containing the user&#039;s driver license.
		 *
		 * @param driverLicense Driver license.
		**/
		public PassportElementDriverLicense(IdentityDocument driverLicense) {
			this.driverLicense = driverLicense;
		}

		/**
		 * A Telegram Passport element containing the user&#039;s driver license.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PassportElementDriverLicense(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (IdentityDocument.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.driverLicense = new IdentityDocument(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PassportElementDriverLicense.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PassportElementDriverLicense.CONSTRUCTOR);
			if (this.driverLicense == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.driverLicense.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PassportElementDriverLicense passportElementDriverLicense = (PassportElementDriverLicense) o;
			if (!Objects.equals(this.driverLicense, passportElementDriverLicense.driverLicense)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.driverLicense == null ? 0 : this.driverLicense.hashCode();
		}
	}

	/**
	 * A Telegram Passport element containing the user&#039;s identity card.
	**/
	public static final class PassportElementIdentityCard extends PassportElement {


		/**
		 * Identity card.
		**/
		public IdentityDocument identityCard;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2083775797;

		/**
		 * A Telegram Passport element containing the user&#039;s identity card.
		**/
		public PassportElementIdentityCard() {}

		/**
		 * A Telegram Passport element containing the user&#039;s identity card.
		 *
		 * @param identityCard Identity card.
		**/
		public PassportElementIdentityCard(IdentityDocument identityCard) {
			this.identityCard = identityCard;
		}

		/**
		 * A Telegram Passport element containing the user&#039;s identity card.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PassportElementIdentityCard(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (IdentityDocument.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.identityCard = new IdentityDocument(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PassportElementIdentityCard.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PassportElementIdentityCard.CONSTRUCTOR);
			if (this.identityCard == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.identityCard.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PassportElementIdentityCard passportElementIdentityCard = (PassportElementIdentityCard) o;
			if (!Objects.equals(this.identityCard, passportElementIdentityCard.identityCard)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.identityCard == null ? 0 : this.identityCard.hashCode();
		}
	}

	/**
	 * A Telegram Passport element containing the user&#039;s internal
	 * passport.
	**/
	public static final class PassportElementInternalPassport extends PassportElement {


		/**
		 * Internal passport.
		**/
		public IdentityDocument internalPassport;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 36220295;

		/**
		 * A Telegram Passport element containing the user&#039;s internal passport.
		**/
		public PassportElementInternalPassport() {}

		/**
		 * A Telegram Passport element containing the user&#039;s internal passport.
		 *
		 * @param internalPassport Internal passport.
		**/
		public PassportElementInternalPassport(IdentityDocument internalPassport) {
			this.internalPassport = internalPassport;
		}

		/**
		 * A Telegram Passport element containing the user&#039;s internal passport.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PassportElementInternalPassport(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (IdentityDocument.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.internalPassport = new IdentityDocument(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PassportElementInternalPassport.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PassportElementInternalPassport.CONSTRUCTOR);
			if (this.internalPassport == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.internalPassport.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PassportElementInternalPassport passportElementInternalPassport = (PassportElementInternalPassport) o;
			if (!Objects.equals(this.internalPassport, passportElementInternalPassport.internalPassport)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.internalPassport == null ? 0 : this.internalPassport.hashCode();
		}
	}

	/**
	 * A Telegram Passport element containing the user&#039;s address.
	**/
	public static final class PassportElementAddress extends PassportElement {


		/**
		 * Address.
		**/
		public Address address;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -782625232;

		/**
		 * A Telegram Passport element containing the user&#039;s address.
		**/
		public PassportElementAddress() {}

		/**
		 * A Telegram Passport element containing the user&#039;s address.
		 *
		 * @param address Address.
		**/
		public PassportElementAddress(Address address) {
			this.address = address;
		}

		/**
		 * A Telegram Passport element containing the user&#039;s address.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PassportElementAddress(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Address.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.address = new Address(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PassportElementAddress.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PassportElementAddress.CONSTRUCTOR);
			if (this.address == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.address.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PassportElementAddress passportElementAddress = (PassportElementAddress) o;
			if (!Objects.equals(this.address, passportElementAddress.address)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.address == null ? 0 : this.address.hashCode();
		}
	}

	/**
	 * A Telegram Passport element containing the user&#039;s utility bill.
	**/
	public static final class PassportElementUtilityBill extends PassportElement {


		/**
		 * Utility bill.
		**/
		public PersonalDocument utilityBill;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -234611246;

		/**
		 * A Telegram Passport element containing the user&#039;s utility bill.
		**/
		public PassportElementUtilityBill() {}

		/**
		 * A Telegram Passport element containing the user&#039;s utility bill.
		 *
		 * @param utilityBill Utility bill.
		**/
		public PassportElementUtilityBill(PersonalDocument utilityBill) {
			this.utilityBill = utilityBill;
		}

		/**
		 * A Telegram Passport element containing the user&#039;s utility bill.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PassportElementUtilityBill(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (PersonalDocument.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.utilityBill = new PersonalDocument(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PassportElementUtilityBill.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PassportElementUtilityBill.CONSTRUCTOR);
			if (this.utilityBill == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.utilityBill.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PassportElementUtilityBill passportElementUtilityBill = (PassportElementUtilityBill) o;
			if (!Objects.equals(this.utilityBill, passportElementUtilityBill.utilityBill)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.utilityBill == null ? 0 : this.utilityBill.hashCode();
		}
	}

	/**
	 * A Telegram Passport element containing the user&#039;s bank statement.
	**/
	public static final class PassportElementBankStatement extends PassportElement {


		/**
		 * Bank statement.
		**/
		public PersonalDocument bankStatement;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -366464408;

		/**
		 * A Telegram Passport element containing the user&#039;s bank statement.
		**/
		public PassportElementBankStatement() {}

		/**
		 * A Telegram Passport element containing the user&#039;s bank statement.
		 *
		 * @param bankStatement Bank statement.
		**/
		public PassportElementBankStatement(PersonalDocument bankStatement) {
			this.bankStatement = bankStatement;
		}

		/**
		 * A Telegram Passport element containing the user&#039;s bank statement.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PassportElementBankStatement(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (PersonalDocument.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.bankStatement = new PersonalDocument(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PassportElementBankStatement.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PassportElementBankStatement.CONSTRUCTOR);
			if (this.bankStatement == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.bankStatement.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PassportElementBankStatement passportElementBankStatement = (PassportElementBankStatement) o;
			if (!Objects.equals(this.bankStatement, passportElementBankStatement.bankStatement)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.bankStatement == null ? 0 : this.bankStatement.hashCode();
		}
	}

	/**
	 * A Telegram Passport element containing the user&#039;s rental
	 * agreement.
	**/
	public static final class PassportElementRentalAgreement extends PassportElement {


		/**
		 * Rental agreement.
		**/
		public PersonalDocument rentalAgreement;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -290141400;

		/**
		 * A Telegram Passport element containing the user&#039;s rental agreement.
		**/
		public PassportElementRentalAgreement() {}

		/**
		 * A Telegram Passport element containing the user&#039;s rental agreement.
		 *
		 * @param rentalAgreement Rental agreement.
		**/
		public PassportElementRentalAgreement(PersonalDocument rentalAgreement) {
			this.rentalAgreement = rentalAgreement;
		}

		/**
		 * A Telegram Passport element containing the user&#039;s rental agreement.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PassportElementRentalAgreement(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (PersonalDocument.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.rentalAgreement = new PersonalDocument(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PassportElementRentalAgreement.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PassportElementRentalAgreement.CONSTRUCTOR);
			if (this.rentalAgreement == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.rentalAgreement.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PassportElementRentalAgreement passportElementRentalAgreement = (PassportElementRentalAgreement) o;
			if (!Objects.equals(this.rentalAgreement, passportElementRentalAgreement.rentalAgreement)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.rentalAgreement == null ? 0 : this.rentalAgreement.hashCode();
		}
	}

	/**
	 * A Telegram Passport element containing the user&#039;s passport
	 * registration pages.
	**/
	public static final class PassportElementPassportRegistration extends PassportElement {


		/**
		 * Passport registration pages.
		**/
		public PersonalDocument passportRegistration;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 618323071;

		/**
		 * A Telegram Passport element containing the user&#039;s passport registration pages.
		**/
		public PassportElementPassportRegistration() {}

		/**
		 * A Telegram Passport element containing the user&#039;s passport registration pages.
		 *
		 * @param passportRegistration Passport registration pages.
		**/
		public PassportElementPassportRegistration(PersonalDocument passportRegistration) {
			this.passportRegistration = passportRegistration;
		}

		/**
		 * A Telegram Passport element containing the user&#039;s passport registration pages.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PassportElementPassportRegistration(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (PersonalDocument.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.passportRegistration = new PersonalDocument(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PassportElementPassportRegistration.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PassportElementPassportRegistration.CONSTRUCTOR);
			if (this.passportRegistration == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.passportRegistration.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PassportElementPassportRegistration passportElementPassportRegistration = (PassportElementPassportRegistration) o;
			if (!Objects.equals(this.passportRegistration, passportElementPassportRegistration.passportRegistration)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.passportRegistration == null ? 0 : this.passportRegistration.hashCode();
		}
	}

	/**
	 * A Telegram Passport element containing the user&#039;s temporary
	 * registration.
	**/
	public static final class PassportElementTemporaryRegistration extends PassportElement {


		/**
		 * Temporary registration.
		**/
		public PersonalDocument temporaryRegistration;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1237626864;

		/**
		 * A Telegram Passport element containing the user&#039;s temporary registration.
		**/
		public PassportElementTemporaryRegistration() {}

		/**
		 * A Telegram Passport element containing the user&#039;s temporary registration.
		 *
		 * @param temporaryRegistration Temporary registration.
		**/
		public PassportElementTemporaryRegistration(PersonalDocument temporaryRegistration) {
			this.temporaryRegistration = temporaryRegistration;
		}

		/**
		 * A Telegram Passport element containing the user&#039;s temporary registration.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PassportElementTemporaryRegistration(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (PersonalDocument.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.temporaryRegistration = new PersonalDocument(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PassportElementTemporaryRegistration.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PassportElementTemporaryRegistration.CONSTRUCTOR);
			if (this.temporaryRegistration == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.temporaryRegistration.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PassportElementTemporaryRegistration passportElementTemporaryRegistration = (PassportElementTemporaryRegistration) o;
			if (!Objects.equals(this.temporaryRegistration, passportElementTemporaryRegistration.temporaryRegistration)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.temporaryRegistration == null ? 0 : this.temporaryRegistration.hashCode();
		}
	}

	/**
	 * A Telegram Passport element containing the user&#039;s phone number.
	**/
	public static final class PassportElementPhoneNumber extends PassportElement {


		/**
		 * Phone number.
		**/
		public String phoneNumber;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1320118375;

		/**
		 * A Telegram Passport element containing the user&#039;s phone number.
		**/
		public PassportElementPhoneNumber() {}

		/**
		 * A Telegram Passport element containing the user&#039;s phone number.
		 *
		 * @param phoneNumber Phone number.
		**/
		public PassportElementPhoneNumber(String phoneNumber) {
			this.phoneNumber = phoneNumber;
		}

		/**
		 * A Telegram Passport element containing the user&#039;s phone number.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PassportElementPhoneNumber(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] phoneNumberTmp = new byte[input.readInt()];
				input.readFully(phoneNumberTmp);
				this.phoneNumber = new String(phoneNumberTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PassportElementPhoneNumber.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PassportElementPhoneNumber.CONSTRUCTOR);
			if (this.phoneNumber == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] phoneNumberTmp = this.phoneNumber.getBytes(StandardCharsets.UTF_8);
				output.writeInt(phoneNumberTmp.length);
				output.write(phoneNumberTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PassportElementPhoneNumber passportElementPhoneNumber = (PassportElementPhoneNumber) o;
			if (this.phoneNumber != passportElementPhoneNumber.phoneNumber) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.phoneNumber == null ? 0 : this.phoneNumber.hashCode();
		}
	}

	/**
	 * A Telegram Passport element containing the user&#039;s email address.
	**/
	public static final class PassportElementEmailAddress extends PassportElement {


		/**
		 * Email address.
		**/
		public String emailAddress;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1528129531;

		/**
		 * A Telegram Passport element containing the user&#039;s email address.
		**/
		public PassportElementEmailAddress() {}

		/**
		 * A Telegram Passport element containing the user&#039;s email address.
		 *
		 * @param emailAddress Email address.
		**/
		public PassportElementEmailAddress(String emailAddress) {
			this.emailAddress = emailAddress;
		}

		/**
		 * A Telegram Passport element containing the user&#039;s email address.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PassportElementEmailAddress(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] emailAddressTmp = new byte[input.readInt()];
				input.readFully(emailAddressTmp);
				this.emailAddress = new String(emailAddressTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PassportElementEmailAddress.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PassportElementEmailAddress.CONSTRUCTOR);
			if (this.emailAddress == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] emailAddressTmp = this.emailAddress.getBytes(StandardCharsets.UTF_8);
				output.writeInt(emailAddressTmp.length);
				output.write(emailAddressTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PassportElementEmailAddress passportElementEmailAddress = (PassportElementEmailAddress) o;
			if (this.emailAddress != passportElementEmailAddress.emailAddress) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.emailAddress == null ? 0 : this.emailAddress.hashCode();
		}
	}

	/**
	 * Contains the description of an error in a Telegram Passport element.
	**/
	public static final class PassportElementError extends Object {


		/**
		 * Type of the Telegram Passport element which has the error.
		**/
		public PassportElementType type;

		/**
		 * Error message.
		**/
		public String message;

		/**
		 * Error source.
		**/
		public PassportElementErrorSource source;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1861902395;

		/**
		 * Contains the description of an error in a Telegram Passport element.
		**/
		public PassportElementError() {}

		/**
		 * Contains the description of an error in a Telegram Passport element.
		 *
		 * @param type Type of the Telegram Passport element which has the error.
		 * @param message Error message.
		 * @param source Error source.
		**/
		public PassportElementError(PassportElementType type,
				String message,
				PassportElementErrorSource source) {
			this.type = type;
			this.message = message;
			this.source = source;
		}

		/**
		 * Contains the description of an error in a Telegram Passport element.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PassportElementError(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case PassportElementTypePersonalDetails.CONSTRUCTOR: this.type = new PassportElementTypePersonalDetails(input); break;
					case PassportElementTypePassport.CONSTRUCTOR: this.type = new PassportElementTypePassport(input); break;
					case PassportElementTypeDriverLicense.CONSTRUCTOR: this.type = new PassportElementTypeDriverLicense(input); break;
					case PassportElementTypeIdentityCard.CONSTRUCTOR: this.type = new PassportElementTypeIdentityCard(input); break;
					case PassportElementTypeInternalPassport.CONSTRUCTOR: this.type = new PassportElementTypeInternalPassport(input); break;
					case PassportElementTypeAddress.CONSTRUCTOR: this.type = new PassportElementTypeAddress(input); break;
					case PassportElementTypeUtilityBill.CONSTRUCTOR: this.type = new PassportElementTypeUtilityBill(input); break;
					case PassportElementTypeBankStatement.CONSTRUCTOR: this.type = new PassportElementTypeBankStatement(input); break;
					case PassportElementTypeRentalAgreement.CONSTRUCTOR: this.type = new PassportElementTypeRentalAgreement(input); break;
					case PassportElementTypePassportRegistration.CONSTRUCTOR: this.type = new PassportElementTypePassportRegistration(input); break;
					case PassportElementTypeTemporaryRegistration.CONSTRUCTOR: this.type = new PassportElementTypeTemporaryRegistration(input); break;
					case PassportElementTypePhoneNumber.CONSTRUCTOR: this.type = new PassportElementTypePhoneNumber(input); break;
					case PassportElementTypeEmailAddress.CONSTRUCTOR: this.type = new PassportElementTypeEmailAddress(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				byte[] messageTmp = new byte[input.readInt()];
				input.readFully(messageTmp);
				this.message = new String(messageTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case PassportElementErrorSourceUnspecified.CONSTRUCTOR: this.source = new PassportElementErrorSourceUnspecified(input); break;
					case PassportElementErrorSourceDataField.CONSTRUCTOR: this.source = new PassportElementErrorSourceDataField(input); break;
					case PassportElementErrorSourceFrontSide.CONSTRUCTOR: this.source = new PassportElementErrorSourceFrontSide(input); break;
					case PassportElementErrorSourceReverseSide.CONSTRUCTOR: this.source = new PassportElementErrorSourceReverseSide(input); break;
					case PassportElementErrorSourceSelfie.CONSTRUCTOR: this.source = new PassportElementErrorSourceSelfie(input); break;
					case PassportElementErrorSourceTranslationFile.CONSTRUCTOR: this.source = new PassportElementErrorSourceTranslationFile(input); break;
					case PassportElementErrorSourceTranslationFiles.CONSTRUCTOR: this.source = new PassportElementErrorSourceTranslationFiles(input); break;
					case PassportElementErrorSourceFile.CONSTRUCTOR: this.source = new PassportElementErrorSourceFile(input); break;
					case PassportElementErrorSourceFiles.CONSTRUCTOR: this.source = new PassportElementErrorSourceFiles(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PassportElementError.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PassportElementError.CONSTRUCTOR);
			if (this.type == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.type.serialize(output);
			}
			if (this.message == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] messageTmp = this.message.getBytes(StandardCharsets.UTF_8);
				output.writeInt(messageTmp.length);
				output.write(messageTmp);
			}
			if (this.source == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.source.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PassportElementError passportElementError = (PassportElementError) o;
			if (!Objects.equals(this.type, passportElementError.type)) {
				return false;
			}
			if (this.message != passportElementError.message) {
				return false;
			}
			if (!Objects.equals(this.source, passportElementError.source)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.type == null ? 0 : this.type.hashCode();
			result = result * 31 + (this.message == null ? 0 : this.message.hashCode());
			result = result * 31 + (this.source == null ? 0 : this.source.hashCode());
			return result;
		}
	}

	/**
	 * The element contains an error in an unspecified place. The error will
	 * be considered resolved when new data is added.
	**/
	public static final class PassportElementErrorSourceUnspecified extends PassportElementErrorSource {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -378320830;

		/**
		 * The element contains an error in an unspecified place. The error will be considered resolved when new data is added.
		**/
		public PassportElementErrorSourceUnspecified() {}

		/**
		 * The element contains an error in an unspecified place. The error will be considered resolved when new data is added.
		 *
		**/

		/**
		 * The element contains an error in an unspecified place. The error will be considered resolved when new data is added.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PassportElementErrorSourceUnspecified(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PassportElementErrorSourceUnspecified.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PassportElementErrorSourceUnspecified.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PassportElementErrorSourceUnspecified.CONSTRUCTOR;
		}
	}

	/**
	 * One of the data fields contains an error. The error will be
	 * considered resolved when the value of the field changes.
	**/
	public static final class PassportElementErrorSourceDataField extends PassportElementErrorSource {


		/**
		 * Field name.
		**/
		public String fieldName;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -308650776;

		/**
		 * One of the data fields contains an error. The error will be considered resolved when the value of the field changes.
		**/
		public PassportElementErrorSourceDataField() {}

		/**
		 * One of the data fields contains an error. The error will be considered resolved when the value of the field changes.
		 *
		 * @param fieldName Field name.
		**/
		public PassportElementErrorSourceDataField(String fieldName) {
			this.fieldName = fieldName;
		}

		/**
		 * One of the data fields contains an error. The error will be considered resolved when the value of the field changes.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PassportElementErrorSourceDataField(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] fieldNameTmp = new byte[input.readInt()];
				input.readFully(fieldNameTmp);
				this.fieldName = new String(fieldNameTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PassportElementErrorSourceDataField.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PassportElementErrorSourceDataField.CONSTRUCTOR);
			if (this.fieldName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] fieldNameTmp = this.fieldName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(fieldNameTmp.length);
				output.write(fieldNameTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PassportElementErrorSourceDataField passportElementErrorSourceDataField = (PassportElementErrorSourceDataField) o;
			if (this.fieldName != passportElementErrorSourceDataField.fieldName) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.fieldName == null ? 0 : this.fieldName.hashCode();
		}
	}

	/**
	 * The front side of the document contains an error. The error will be
	 * considered resolved when the file with the front side changes.
	**/
	public static final class PassportElementErrorSourceFrontSide extends PassportElementErrorSource {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1895658292;

		/**
		 * The front side of the document contains an error. The error will be considered resolved when the file with the front side changes.
		**/
		public PassportElementErrorSourceFrontSide() {}

		/**
		 * The front side of the document contains an error. The error will be considered resolved when the file with the front side changes.
		 *
		**/

		/**
		 * The front side of the document contains an error. The error will be considered resolved when the file with the front side changes.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PassportElementErrorSourceFrontSide(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PassportElementErrorSourceFrontSide.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PassportElementErrorSourceFrontSide.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PassportElementErrorSourceFrontSide.CONSTRUCTOR;
		}
	}

	/**
	 * The reverse side of the document contains an error. The error will be
	 * considered resolved when the file with the reverse side changes.
	**/
	public static final class PassportElementErrorSourceReverseSide extends PassportElementErrorSource {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1918630391;

		/**
		 * The reverse side of the document contains an error. The error will be considered resolved when the file with the reverse side changes.
		**/
		public PassportElementErrorSourceReverseSide() {}

		/**
		 * The reverse side of the document contains an error. The error will be considered resolved when the file with the reverse side changes.
		 *
		**/

		/**
		 * The reverse side of the document contains an error. The error will be considered resolved when the file with the reverse side changes.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PassportElementErrorSourceReverseSide(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PassportElementErrorSourceReverseSide.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PassportElementErrorSourceReverseSide.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PassportElementErrorSourceReverseSide.CONSTRUCTOR;
		}
	}

	/**
	 * The selfie with the document contains an error. The error will be
	 * considered resolved when the file with the selfie changes.
	**/
	public static final class PassportElementErrorSourceSelfie extends PassportElementErrorSource {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -797043672;

		/**
		 * The selfie with the document contains an error. The error will be considered resolved when the file with the selfie changes.
		**/
		public PassportElementErrorSourceSelfie() {}

		/**
		 * The selfie with the document contains an error. The error will be considered resolved when the file with the selfie changes.
		 *
		**/

		/**
		 * The selfie with the document contains an error. The error will be considered resolved when the file with the selfie changes.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PassportElementErrorSourceSelfie(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PassportElementErrorSourceSelfie.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PassportElementErrorSourceSelfie.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PassportElementErrorSourceSelfie.CONSTRUCTOR;
		}
	}

	/**
	 * One of files with the translation of the document contains an error.
	 * The error will be considered resolved when the file changes.
	**/
	public static final class PassportElementErrorSourceTranslationFile extends PassportElementErrorSource {


		/**
		 * Index of a file with the error.
		**/
		public int fileIndex;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -689621228;

		/**
		 * One of files with the translation of the document contains an error. The error will be considered resolved when the file changes.
		**/
		public PassportElementErrorSourceTranslationFile() {}

		/**
		 * One of files with the translation of the document contains an error. The error will be considered resolved when the file changes.
		 *
		 * @param fileIndex Index of a file with the error.
		**/
		public PassportElementErrorSourceTranslationFile(int fileIndex) {
			this.fileIndex = fileIndex;
		}

		/**
		 * One of files with the translation of the document contains an error. The error will be considered resolved when the file changes.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PassportElementErrorSourceTranslationFile(DataInput input) throws IOException {
			this.fileIndex = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PassportElementErrorSourceTranslationFile.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PassportElementErrorSourceTranslationFile.CONSTRUCTOR);
			output.writeInt(this.fileIndex);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PassportElementErrorSourceTranslationFile passportElementErrorSourceTranslationFile = (PassportElementErrorSourceTranslationFile) o;
			if (this.fileIndex != passportElementErrorSourceTranslationFile.fileIndex) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.fileIndex);
		}
	}

	/**
	 * The translation of the document contains an error. The error will be
	 * considered resolved when the list of translation files changes.
	**/
	public static final class PassportElementErrorSourceTranslationFiles extends PassportElementErrorSource {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 581280796;

		/**
		 * The translation of the document contains an error. The error will be considered resolved when the list of translation files changes.
		**/
		public PassportElementErrorSourceTranslationFiles() {}

		/**
		 * The translation of the document contains an error. The error will be considered resolved when the list of translation files changes.
		 *
		**/

		/**
		 * The translation of the document contains an error. The error will be considered resolved when the list of translation files changes.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PassportElementErrorSourceTranslationFiles(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PassportElementErrorSourceTranslationFiles.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PassportElementErrorSourceTranslationFiles.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PassportElementErrorSourceTranslationFiles.CONSTRUCTOR;
		}
	}

	/**
	 * The file contains an error. The error will be considered resolved
	 * when the file changes.
	**/
	public static final class PassportElementErrorSourceFile extends PassportElementErrorSource {


		/**
		 * Index of a file with the error.
		**/
		public int fileIndex;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2020358960;

		/**
		 * The file contains an error. The error will be considered resolved when the file changes.
		**/
		public PassportElementErrorSourceFile() {}

		/**
		 * The file contains an error. The error will be considered resolved when the file changes.
		 *
		 * @param fileIndex Index of a file with the error.
		**/
		public PassportElementErrorSourceFile(int fileIndex) {
			this.fileIndex = fileIndex;
		}

		/**
		 * The file contains an error. The error will be considered resolved when the file changes.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PassportElementErrorSourceFile(DataInput input) throws IOException {
			this.fileIndex = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PassportElementErrorSourceFile.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PassportElementErrorSourceFile.CONSTRUCTOR);
			output.writeInt(this.fileIndex);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PassportElementErrorSourceFile passportElementErrorSourceFile = (PassportElementErrorSourceFile) o;
			if (this.fileIndex != passportElementErrorSourceFile.fileIndex) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.fileIndex);
		}
	}

	/**
	 * The list of attached files contains an error. The error will be
	 * considered resolved when the list of files changes.
	**/
	public static final class PassportElementErrorSourceFiles extends PassportElementErrorSource {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1894164178;

		/**
		 * The list of attached files contains an error. The error will be considered resolved when the list of files changes.
		**/
		public PassportElementErrorSourceFiles() {}

		/**
		 * The list of attached files contains an error. The error will be considered resolved when the list of files changes.
		 *
		**/

		/**
		 * The list of attached files contains an error. The error will be considered resolved when the list of files changes.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PassportElementErrorSourceFiles(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PassportElementErrorSourceFiles.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PassportElementErrorSourceFiles.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PassportElementErrorSourceFiles.CONSTRUCTOR;
		}
	}

	/**
	 * A Telegram Passport element containing the user&#039;s personal
	 * details.
	**/
	public static final class PassportElementTypePersonalDetails extends PassportElementType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1032136365;

		/**
		 * A Telegram Passport element containing the user&#039;s personal details.
		**/
		public PassportElementTypePersonalDetails() {}

		/**
		 * A Telegram Passport element containing the user&#039;s personal details.
		 *
		**/

		/**
		 * A Telegram Passport element containing the user&#039;s personal details.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PassportElementTypePersonalDetails(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PassportElementTypePersonalDetails.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PassportElementTypePersonalDetails.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PassportElementTypePersonalDetails.CONSTRUCTOR;
		}
	}

	/**
	 * A Telegram Passport element containing the user&#039;s passport.
	**/
	public static final class PassportElementTypePassport extends PassportElementType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -436360376;

		/**
		 * A Telegram Passport element containing the user&#039;s passport.
		**/
		public PassportElementTypePassport() {}

		/**
		 * A Telegram Passport element containing the user&#039;s passport.
		 *
		**/

		/**
		 * A Telegram Passport element containing the user&#039;s passport.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PassportElementTypePassport(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PassportElementTypePassport.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PassportElementTypePassport.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PassportElementTypePassport.CONSTRUCTOR;
		}
	}

	/**
	 * A Telegram Passport element containing the user&#039;s driver license.
	**/
	public static final class PassportElementTypeDriverLicense extends PassportElementType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1827298379;

		/**
		 * A Telegram Passport element containing the user&#039;s driver license.
		**/
		public PassportElementTypeDriverLicense() {}

		/**
		 * A Telegram Passport element containing the user&#039;s driver license.
		 *
		**/

		/**
		 * A Telegram Passport element containing the user&#039;s driver license.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PassportElementTypeDriverLicense(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PassportElementTypeDriverLicense.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PassportElementTypeDriverLicense.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PassportElementTypeDriverLicense.CONSTRUCTOR;
		}
	}

	/**
	 * A Telegram Passport element containing the user&#039;s identity card.
	**/
	public static final class PassportElementTypeIdentityCard extends PassportElementType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -502356132;

		/**
		 * A Telegram Passport element containing the user&#039;s identity card.
		**/
		public PassportElementTypeIdentityCard() {}

		/**
		 * A Telegram Passport element containing the user&#039;s identity card.
		 *
		**/

		/**
		 * A Telegram Passport element containing the user&#039;s identity card.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PassportElementTypeIdentityCard(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PassportElementTypeIdentityCard.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PassportElementTypeIdentityCard.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PassportElementTypeIdentityCard.CONSTRUCTOR;
		}
	}

	/**
	 * A Telegram Passport element containing the user&#039;s internal
	 * passport.
	**/
	public static final class PassportElementTypeInternalPassport extends PassportElementType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -793781959;

		/**
		 * A Telegram Passport element containing the user&#039;s internal passport.
		**/
		public PassportElementTypeInternalPassport() {}

		/**
		 * A Telegram Passport element containing the user&#039;s internal passport.
		 *
		**/

		/**
		 * A Telegram Passport element containing the user&#039;s internal passport.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PassportElementTypeInternalPassport(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PassportElementTypeInternalPassport.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PassportElementTypeInternalPassport.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PassportElementTypeInternalPassport.CONSTRUCTOR;
		}
	}

	/**
	 * A Telegram Passport element containing the user&#039;s address.
	**/
	public static final class PassportElementTypeAddress extends PassportElementType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 496327874;

		/**
		 * A Telegram Passport element containing the user&#039;s address.
		**/
		public PassportElementTypeAddress() {}

		/**
		 * A Telegram Passport element containing the user&#039;s address.
		 *
		**/

		/**
		 * A Telegram Passport element containing the user&#039;s address.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PassportElementTypeAddress(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PassportElementTypeAddress.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PassportElementTypeAddress.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PassportElementTypeAddress.CONSTRUCTOR;
		}
	}

	/**
	 * A Telegram Passport element containing the user&#039;s utility bill.
	**/
	public static final class PassportElementTypeUtilityBill extends PassportElementType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 627084906;

		/**
		 * A Telegram Passport element containing the user&#039;s utility bill.
		**/
		public PassportElementTypeUtilityBill() {}

		/**
		 * A Telegram Passport element containing the user&#039;s utility bill.
		 *
		**/

		/**
		 * A Telegram Passport element containing the user&#039;s utility bill.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PassportElementTypeUtilityBill(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PassportElementTypeUtilityBill.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PassportElementTypeUtilityBill.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PassportElementTypeUtilityBill.CONSTRUCTOR;
		}
	}

	/**
	 * A Telegram Passport element containing the user&#039;s bank statement.
	**/
	public static final class PassportElementTypeBankStatement extends PassportElementType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 574095667;

		/**
		 * A Telegram Passport element containing the user&#039;s bank statement.
		**/
		public PassportElementTypeBankStatement() {}

		/**
		 * A Telegram Passport element containing the user&#039;s bank statement.
		 *
		**/

		/**
		 * A Telegram Passport element containing the user&#039;s bank statement.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PassportElementTypeBankStatement(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PassportElementTypeBankStatement.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PassportElementTypeBankStatement.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PassportElementTypeBankStatement.CONSTRUCTOR;
		}
	}

	/**
	 * A Telegram Passport element containing the user&#039;s rental
	 * agreement.
	**/
	public static final class PassportElementTypeRentalAgreement extends PassportElementType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2060583280;

		/**
		 * A Telegram Passport element containing the user&#039;s rental agreement.
		**/
		public PassportElementTypeRentalAgreement() {}

		/**
		 * A Telegram Passport element containing the user&#039;s rental agreement.
		 *
		**/

		/**
		 * A Telegram Passport element containing the user&#039;s rental agreement.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PassportElementTypeRentalAgreement(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PassportElementTypeRentalAgreement.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PassportElementTypeRentalAgreement.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PassportElementTypeRentalAgreement.CONSTRUCTOR;
		}
	}

	/**
	 * A Telegram Passport element containing the registration page of the
	 * user&#039;s passport.
	**/
	public static final class PassportElementTypePassportRegistration extends PassportElementType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -159478209;

		/**
		 * A Telegram Passport element containing the registration page of the user&#039;s passport.
		**/
		public PassportElementTypePassportRegistration() {}

		/**
		 * A Telegram Passport element containing the registration page of the user&#039;s passport.
		 *
		**/

		/**
		 * A Telegram Passport element containing the registration page of the user&#039;s passport.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PassportElementTypePassportRegistration(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PassportElementTypePassportRegistration.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PassportElementTypePassportRegistration.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PassportElementTypePassportRegistration.CONSTRUCTOR;
		}
	}

	/**
	 * A Telegram Passport element containing the user&#039;s temporary
	 * registration.
	**/
	public static final class PassportElementTypeTemporaryRegistration extends PassportElementType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1092498527;

		/**
		 * A Telegram Passport element containing the user&#039;s temporary registration.
		**/
		public PassportElementTypeTemporaryRegistration() {}

		/**
		 * A Telegram Passport element containing the user&#039;s temporary registration.
		 *
		**/

		/**
		 * A Telegram Passport element containing the user&#039;s temporary registration.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PassportElementTypeTemporaryRegistration(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PassportElementTypeTemporaryRegistration.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PassportElementTypeTemporaryRegistration.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PassportElementTypeTemporaryRegistration.CONSTRUCTOR;
		}
	}

	/**
	 * A Telegram Passport element containing the user&#039;s phone number.
	**/
	public static final class PassportElementTypePhoneNumber extends PassportElementType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -995361172;

		/**
		 * A Telegram Passport element containing the user&#039;s phone number.
		**/
		public PassportElementTypePhoneNumber() {}

		/**
		 * A Telegram Passport element containing the user&#039;s phone number.
		 *
		**/

		/**
		 * A Telegram Passport element containing the user&#039;s phone number.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PassportElementTypePhoneNumber(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PassportElementTypePhoneNumber.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PassportElementTypePhoneNumber.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PassportElementTypePhoneNumber.CONSTRUCTOR;
		}
	}

	/**
	 * A Telegram Passport element containing the user&#039;s email address.
	**/
	public static final class PassportElementTypeEmailAddress extends PassportElementType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -79321405;

		/**
		 * A Telegram Passport element containing the user&#039;s email address.
		**/
		public PassportElementTypeEmailAddress() {}

		/**
		 * A Telegram Passport element containing the user&#039;s email address.
		 *
		**/

		/**
		 * A Telegram Passport element containing the user&#039;s email address.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PassportElementTypeEmailAddress(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PassportElementTypeEmailAddress.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PassportElementTypeEmailAddress.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PassportElementTypeEmailAddress.CONSTRUCTOR;
		}
	}

	/**
	 * Contains information about saved Telegram Passport elements.
	**/
	public static final class PassportElements extends Object {


		/**
		 * Telegram Passport elements.
		**/
		public PassportElement[] elements;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1264617556;

		/**
		 * Contains information about saved Telegram Passport elements.
		**/
		public PassportElements() {}

		/**
		 * Contains information about saved Telegram Passport elements.
		 *
		 * @param elements Telegram Passport elements.
		**/
		public PassportElements(PassportElement[] elements) {
			this.elements = elements;
		}

		/**
		 * Contains information about saved Telegram Passport elements.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PassportElements(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.elements = new PassportElement[input.readInt()];
				for (int i = 0; i < this.elements.length; i++) {
					switch(input.readInt()) {
						case PassportElementPersonalDetails.CONSTRUCTOR: this.elements[i] = new PassportElementPersonalDetails(input); break;
						case PassportElementPassport.CONSTRUCTOR: this.elements[i] = new PassportElementPassport(input); break;
						case PassportElementDriverLicense.CONSTRUCTOR: this.elements[i] = new PassportElementDriverLicense(input); break;
						case PassportElementIdentityCard.CONSTRUCTOR: this.elements[i] = new PassportElementIdentityCard(input); break;
						case PassportElementInternalPassport.CONSTRUCTOR: this.elements[i] = new PassportElementInternalPassport(input); break;
						case PassportElementAddress.CONSTRUCTOR: this.elements[i] = new PassportElementAddress(input); break;
						case PassportElementUtilityBill.CONSTRUCTOR: this.elements[i] = new PassportElementUtilityBill(input); break;
						case PassportElementBankStatement.CONSTRUCTOR: this.elements[i] = new PassportElementBankStatement(input); break;
						case PassportElementRentalAgreement.CONSTRUCTOR: this.elements[i] = new PassportElementRentalAgreement(input); break;
						case PassportElementPassportRegistration.CONSTRUCTOR: this.elements[i] = new PassportElementPassportRegistration(input); break;
						case PassportElementTemporaryRegistration.CONSTRUCTOR: this.elements[i] = new PassportElementTemporaryRegistration(input); break;
						case PassportElementPhoneNumber.CONSTRUCTOR: this.elements[i] = new PassportElementPhoneNumber(input); break;
						case PassportElementEmailAddress.CONSTRUCTOR: this.elements[i] = new PassportElementEmailAddress(input); break;
						default: {
							throw new UnsupportedOperationException();
						}
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PassportElements.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PassportElements.CONSTRUCTOR);
			if (this.elements == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.elements.length);
				for (int i = 0; i < this.elements.length; i++) {
					this.elements[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PassportElements passportElements = (PassportElements) o;
			if (!Arrays.equals(this.elements, passportElements.elements)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.elements);
		}
	}

	/**
	 * Contains information about a Telegram Passport elements and
	 * corresponding errors.
	**/
	public static final class PassportElementsWithErrors extends Object {


		/**
		 * Telegram Passport elements.
		**/
		public PassportElement[] elements;

		/**
		 * Errors in the elements that are already available.
		**/
		public PassportElementError[] errors;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1308923044;

		/**
		 * Contains information about a Telegram Passport elements and corresponding errors.
		**/
		public PassportElementsWithErrors() {}

		/**
		 * Contains information about a Telegram Passport elements and corresponding errors.
		 *
		 * @param elements Telegram Passport elements.
		 * @param errors Errors in the elements that are already available.
		**/
		public PassportElementsWithErrors(PassportElement[] elements, PassportElementError[] errors) {
			this.elements = elements;
			this.errors = errors;
		}

		/**
		 * Contains information about a Telegram Passport elements and corresponding errors.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PassportElementsWithErrors(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.elements = new PassportElement[input.readInt()];
				for (int i = 0; i < this.elements.length; i++) {
					switch(input.readInt()) {
						case PassportElementPersonalDetails.CONSTRUCTOR: this.elements[i] = new PassportElementPersonalDetails(input); break;
						case PassportElementPassport.CONSTRUCTOR: this.elements[i] = new PassportElementPassport(input); break;
						case PassportElementDriverLicense.CONSTRUCTOR: this.elements[i] = new PassportElementDriverLicense(input); break;
						case PassportElementIdentityCard.CONSTRUCTOR: this.elements[i] = new PassportElementIdentityCard(input); break;
						case PassportElementInternalPassport.CONSTRUCTOR: this.elements[i] = new PassportElementInternalPassport(input); break;
						case PassportElementAddress.CONSTRUCTOR: this.elements[i] = new PassportElementAddress(input); break;
						case PassportElementUtilityBill.CONSTRUCTOR: this.elements[i] = new PassportElementUtilityBill(input); break;
						case PassportElementBankStatement.CONSTRUCTOR: this.elements[i] = new PassportElementBankStatement(input); break;
						case PassportElementRentalAgreement.CONSTRUCTOR: this.elements[i] = new PassportElementRentalAgreement(input); break;
						case PassportElementPassportRegistration.CONSTRUCTOR: this.elements[i] = new PassportElementPassportRegistration(input); break;
						case PassportElementTemporaryRegistration.CONSTRUCTOR: this.elements[i] = new PassportElementTemporaryRegistration(input); break;
						case PassportElementPhoneNumber.CONSTRUCTOR: this.elements[i] = new PassportElementPhoneNumber(input); break;
						case PassportElementEmailAddress.CONSTRUCTOR: this.elements[i] = new PassportElementEmailAddress(input); break;
						default: {
							throw new UnsupportedOperationException();
						}
					}
				}
			}
			if (input.readBoolean()) {
				this.errors = new PassportElementError[input.readInt()];
				for (int i = 0; i < this.errors.length; i++) {
					if (PassportElementError.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.errors[i] = new PassportElementError(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PassportElementsWithErrors.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PassportElementsWithErrors.CONSTRUCTOR);
			if (this.elements == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.elements.length);
				for (int i = 0; i < this.elements.length; i++) {
					this.elements[i].serialize(output);
				}
			}
			if (this.errors == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.errors.length);
				for (int i = 0; i < this.errors.length; i++) {
					this.errors[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PassportElementsWithErrors passportElementsWithErrors = (PassportElementsWithErrors) o;
			if (!Arrays.equals(this.elements, passportElementsWithErrors.elements)) {
				return false;
			}
			if (!Arrays.equals(this.errors, passportElementsWithErrors.errors)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Arrays.hashCode(this.elements);
			result = result * 31 + (Arrays.hashCode(this.errors));
			return result;
		}
	}

	/**
	 * Contains a description of the required Telegram Passport element that
	 * was requested by a service.
	**/
	public static final class PassportRequiredElement extends Object {


		/**
		 * List of Telegram Passport elements any of which is enough to provide.
		**/
		public PassportSuitableElement[] suitableElements;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1983641651;

		/**
		 * Contains a description of the required Telegram Passport element that was requested by a service.
		**/
		public PassportRequiredElement() {}

		/**
		 * Contains a description of the required Telegram Passport element that was requested by a service.
		 *
		 * @param suitableElements List of Telegram Passport elements any of which is enough to provide.
		**/
		public PassportRequiredElement(PassportSuitableElement[] suitableElements) {
			this.suitableElements = suitableElements;
		}

		/**
		 * Contains a description of the required Telegram Passport element that was requested by a service.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PassportRequiredElement(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.suitableElements = new PassportSuitableElement[input.readInt()];
				for (int i = 0; i < this.suitableElements.length; i++) {
					if (PassportSuitableElement.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.suitableElements[i] = new PassportSuitableElement(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PassportRequiredElement.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PassportRequiredElement.CONSTRUCTOR);
			if (this.suitableElements == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.suitableElements.length);
				for (int i = 0; i < this.suitableElements.length; i++) {
					this.suitableElements[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PassportRequiredElement passportRequiredElement = (PassportRequiredElement) o;
			if (!Arrays.equals(this.suitableElements, passportRequiredElement.suitableElements)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.suitableElements);
		}
	}

	/**
	 * Contains information about a Telegram Passport element that was
	 * requested by a service.
	**/
	public static final class PassportSuitableElement extends Object {


		/**
		 * Type of the element.
		**/
		public PassportElementType type;

		/**
		 * True, if a selfie is required with the identity document.
		**/
		public boolean isSelfieRequired;

		/**
		 * True, if a certified English translation is required with the document.
		**/
		public boolean isTranslationRequired;

		/**
		 * True, if personal details must include the user&#039;s name in the language of their country of residence.
		**/
		public boolean isNativeNameRequired;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -789019876;

		/**
		 * Contains information about a Telegram Passport element that was requested by a service.
		**/
		public PassportSuitableElement() {}

		/**
		 * Contains information about a Telegram Passport element that was requested by a service.
		 *
		 * @param type Type of the element.
		 * @param isSelfieRequired True, if a selfie is required with the identity document.
		 * @param isTranslationRequired True, if a certified English translation is required with the document.
		 * @param isNativeNameRequired True, if personal details must include the user&#039;s name in the language of their country of residence.
		**/
		public PassportSuitableElement(PassportElementType type,
				boolean isSelfieRequired,
				boolean isTranslationRequired,
				boolean isNativeNameRequired) {
			this.type = type;
			this.isSelfieRequired = isSelfieRequired;
			this.isTranslationRequired = isTranslationRequired;
			this.isNativeNameRequired = isNativeNameRequired;
		}

		/**
		 * Contains information about a Telegram Passport element that was requested by a service.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PassportSuitableElement(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case PassportElementTypePersonalDetails.CONSTRUCTOR: this.type = new PassportElementTypePersonalDetails(input); break;
					case PassportElementTypePassport.CONSTRUCTOR: this.type = new PassportElementTypePassport(input); break;
					case PassportElementTypeDriverLicense.CONSTRUCTOR: this.type = new PassportElementTypeDriverLicense(input); break;
					case PassportElementTypeIdentityCard.CONSTRUCTOR: this.type = new PassportElementTypeIdentityCard(input); break;
					case PassportElementTypeInternalPassport.CONSTRUCTOR: this.type = new PassportElementTypeInternalPassport(input); break;
					case PassportElementTypeAddress.CONSTRUCTOR: this.type = new PassportElementTypeAddress(input); break;
					case PassportElementTypeUtilityBill.CONSTRUCTOR: this.type = new PassportElementTypeUtilityBill(input); break;
					case PassportElementTypeBankStatement.CONSTRUCTOR: this.type = new PassportElementTypeBankStatement(input); break;
					case PassportElementTypeRentalAgreement.CONSTRUCTOR: this.type = new PassportElementTypeRentalAgreement(input); break;
					case PassportElementTypePassportRegistration.CONSTRUCTOR: this.type = new PassportElementTypePassportRegistration(input); break;
					case PassportElementTypeTemporaryRegistration.CONSTRUCTOR: this.type = new PassportElementTypeTemporaryRegistration(input); break;
					case PassportElementTypePhoneNumber.CONSTRUCTOR: this.type = new PassportElementTypePhoneNumber(input); break;
					case PassportElementTypeEmailAddress.CONSTRUCTOR: this.type = new PassportElementTypeEmailAddress(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.isSelfieRequired = input.readBoolean();
			this.isTranslationRequired = input.readBoolean();
			this.isNativeNameRequired = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PassportSuitableElement.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PassportSuitableElement.CONSTRUCTOR);
			if (this.type == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.type.serialize(output);
			}
			output.writeBoolean(this.isSelfieRequired);
			output.writeBoolean(this.isTranslationRequired);
			output.writeBoolean(this.isNativeNameRequired);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PassportSuitableElement passportSuitableElement = (PassportSuitableElement) o;
			if (!Objects.equals(this.type, passportSuitableElement.type)) {
				return false;
			}
			if (this.isSelfieRequired != passportSuitableElement.isSelfieRequired) {
				return false;
			}
			if (this.isTranslationRequired != passportSuitableElement.isTranslationRequired) {
				return false;
			}
			if (this.isNativeNameRequired != passportSuitableElement.isNativeNameRequired) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isSelfieRequired);
			result = result * 31 + (this.type == null ? 0 : this.type.hashCode());
			return result;
		}
	}

	/**
	 * Represents the current state of 2-step verification.
	**/
	public static final class PasswordState extends Object {


		/**
		 * True, if a 2-step verification password is set.
		**/
		public boolean hasPassword;

		/**
		 * Hint for the password; may be empty.
		**/
		public String passwordHint;

		/**
		 * True, if a recovery email is set.
		**/
		public boolean hasRecoveryEmailAddress;

		/**
		 * True, if some Telegram Passport elements were saved.
		**/
		public boolean hasPassportData;

		/**
		 * Information about the recovery email address to which the confirmation email was sent; may be null.
		**/
		public EmailAddressAuthenticationCodeInfo recoveryEmailAddressCodeInfo;

		/**
		 * Pattern of the email address set up for logging in.
		**/
		public String loginEmailAddressPattern;

		/**
		 * If not 0, point in time (Unix timestamp) after which the 2-step verification password can be reset immediately using resetPassword.
		**/
		public int pendingResetDate;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 483801128;

		/**
		 * Represents the current state of 2-step verification.
		**/
		public PasswordState() {}

		/**
		 * Represents the current state of 2-step verification.
		 *
		 * @param hasPassword True, if a 2-step verification password is set.
		 * @param passwordHint Hint for the password; may be empty.
		 * @param hasRecoveryEmailAddress True, if a recovery email is set.
		 * @param hasPassportData True, if some Telegram Passport elements were saved.
		 * @param recoveryEmailAddressCodeInfo Information about the recovery email address to which the confirmation email was sent; may be null.
		 * @param loginEmailAddressPattern Pattern of the email address set up for logging in.
		 * @param pendingResetDate If not 0, point in time (Unix timestamp) after which the 2-step verification password can be reset immediately using resetPassword.
		**/
		public PasswordState(boolean hasPassword,
				String passwordHint,
				boolean hasRecoveryEmailAddress,
				boolean hasPassportData,
				EmailAddressAuthenticationCodeInfo recoveryEmailAddressCodeInfo,
				String loginEmailAddressPattern,
				int pendingResetDate) {
			this.hasPassword = hasPassword;
			this.passwordHint = passwordHint;
			this.hasRecoveryEmailAddress = hasRecoveryEmailAddress;
			this.hasPassportData = hasPassportData;
			this.recoveryEmailAddressCodeInfo = recoveryEmailAddressCodeInfo;
			this.loginEmailAddressPattern = loginEmailAddressPattern;
			this.pendingResetDate = pendingResetDate;
		}

		/**
		 * Represents the current state of 2-step verification.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PasswordState(DataInput input) throws IOException {
			this.hasPassword = input.readBoolean();
			if (input.readBoolean()) {
				byte[] passwordHintTmp = new byte[input.readInt()];
				input.readFully(passwordHintTmp);
				this.passwordHint = new String(passwordHintTmp, StandardCharsets.UTF_8);
			}
			this.hasRecoveryEmailAddress = input.readBoolean();
			this.hasPassportData = input.readBoolean();
			if (input.readBoolean()) {
				if (EmailAddressAuthenticationCodeInfo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.recoveryEmailAddressCodeInfo = new EmailAddressAuthenticationCodeInfo(input);
			}
			if (input.readBoolean()) {
				byte[] loginEmailAddressPatternTmp = new byte[input.readInt()];
				input.readFully(loginEmailAddressPatternTmp);
				this.loginEmailAddressPattern = new String(loginEmailAddressPatternTmp, StandardCharsets.UTF_8);
			}
			this.pendingResetDate = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PasswordState.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PasswordState.CONSTRUCTOR);
			output.writeBoolean(this.hasPassword);
			if (this.passwordHint == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] passwordHintTmp = this.passwordHint.getBytes(StandardCharsets.UTF_8);
				output.writeInt(passwordHintTmp.length);
				output.write(passwordHintTmp);
			}
			output.writeBoolean(this.hasRecoveryEmailAddress);
			output.writeBoolean(this.hasPassportData);
			if (this.recoveryEmailAddressCodeInfo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.recoveryEmailAddressCodeInfo.serialize(output);
			}
			if (this.loginEmailAddressPattern == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] loginEmailAddressPatternTmp = this.loginEmailAddressPattern.getBytes(StandardCharsets.UTF_8);
				output.writeInt(loginEmailAddressPatternTmp.length);
				output.write(loginEmailAddressPatternTmp);
			}
			output.writeInt(this.pendingResetDate);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PasswordState passwordState = (PasswordState) o;
			if (this.hasPassword != passwordState.hasPassword) {
				return false;
			}
			if (this.passwordHint != passwordState.passwordHint) {
				return false;
			}
			if (this.hasRecoveryEmailAddress != passwordState.hasRecoveryEmailAddress) {
				return false;
			}
			if (this.hasPassportData != passwordState.hasPassportData) {
				return false;
			}
			if (!Objects.equals(this.recoveryEmailAddressCodeInfo, passwordState.recoveryEmailAddressCodeInfo)) {
				return false;
			}
			if (this.loginEmailAddressPattern != passwordState.loginEmailAddressPattern) {
				return false;
			}
			if (this.pendingResetDate != passwordState.pendingResetDate) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.hasPassword);
			result = result * 31 + (this.passwordHint == null ? 0 : this.passwordHint.hashCode());
			result = result * 31 + (this.recoveryEmailAddressCodeInfo == null ? 0 : this.recoveryEmailAddressCodeInfo.hashCode());
			result = result * 31 + (this.loginEmailAddressPattern == null ? 0 : this.loginEmailAddressPattern.hashCode());
			return result;
		}
	}

	/**
	 * Contains information about an invoice payment form.
	**/
	public static final class PaymentForm extends Object {


		/**
		 * The payment form identifier.
		**/
		public long id;

		/**
		 * Full information about the invoice.
		**/
		public Invoice invoice;

		/**
		 * User identifier of the seller bot.
		**/
		public long sellerBotUserId;

		/**
		 * User identifier of the payment provider bot.
		**/
		public long paymentProviderUserId;

		/**
		 * Information about the payment provider.
		**/
		public PaymentProvider paymentProvider;

		/**
		 * The list of additional payment options.
		**/
		public PaymentOption[] additionalPaymentOptions;

		/**
		 * Saved server-side order information; may be null.
		**/
		public OrderInfo savedOrderInfo;

		/**
		 * The list of saved payment credentials.
		**/
		public SavedCredentials[] savedCredentials;

		/**
		 * True, if the user can choose to save credentials.
		**/
		public boolean canSaveCredentials;

		/**
		 * True, if the user will be able to save credentials, if sets up a 2-step verification password.
		**/
		public boolean needPassword;

		/**
		 * Product title.
		**/
		public String productTitle;

		/**
		 * Product description.
		**/
		public FormattedText productDescription;

		/**
		 * Product photo; may be null.
		**/
		public Photo productPhoto;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1468471378;

		/**
		 * Contains information about an invoice payment form.
		**/
		public PaymentForm() {}

		/**
		 * Contains information about an invoice payment form.
		 *
		 * @param id The payment form identifier.
		 * @param invoice Full information about the invoice.
		 * @param sellerBotUserId User identifier of the seller bot.
		 * @param paymentProviderUserId User identifier of the payment provider bot.
		 * @param paymentProvider Information about the payment provider.
		 * @param additionalPaymentOptions The list of additional payment options.
		 * @param savedOrderInfo Saved server-side order information; may be null.
		 * @param savedCredentials The list of saved payment credentials.
		 * @param canSaveCredentials True, if the user can choose to save credentials.
		 * @param needPassword True, if the user will be able to save credentials, if sets up a 2-step verification password.
		 * @param productTitle Product title.
		 * @param productDescription Product description.
		 * @param productPhoto Product photo; may be null.
		**/
		public PaymentForm(long id,
				Invoice invoice,
				long sellerBotUserId,
				long paymentProviderUserId,
				PaymentProvider paymentProvider,
				PaymentOption[] additionalPaymentOptions,
				OrderInfo savedOrderInfo,
				SavedCredentials[] savedCredentials,
				boolean canSaveCredentials,
				boolean needPassword,
				String productTitle,
				FormattedText productDescription,
				Photo productPhoto) {
			this.id = id;
			this.invoice = invoice;
			this.sellerBotUserId = sellerBotUserId;
			this.paymentProviderUserId = paymentProviderUserId;
			this.paymentProvider = paymentProvider;
			this.additionalPaymentOptions = additionalPaymentOptions;
			this.savedOrderInfo = savedOrderInfo;
			this.savedCredentials = savedCredentials;
			this.canSaveCredentials = canSaveCredentials;
			this.needPassword = needPassword;
			this.productTitle = productTitle;
			this.productDescription = productDescription;
			this.productPhoto = productPhoto;
		}

		/**
		 * Contains information about an invoice payment form.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PaymentForm(DataInput input) throws IOException {
			this.id = input.readLong();
			if (input.readBoolean()) {
				if (Invoice.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.invoice = new Invoice(input);
			}
			this.sellerBotUserId = input.readLong();
			this.paymentProviderUserId = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case PaymentProviderSmartGlocal.CONSTRUCTOR: this.paymentProvider = new PaymentProviderSmartGlocal(input); break;
					case PaymentProviderStripe.CONSTRUCTOR: this.paymentProvider = new PaymentProviderStripe(input); break;
					case PaymentProviderOther.CONSTRUCTOR: this.paymentProvider = new PaymentProviderOther(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				this.additionalPaymentOptions = new PaymentOption[input.readInt()];
				for (int i = 0; i < this.additionalPaymentOptions.length; i++) {
					if (PaymentOption.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.additionalPaymentOptions[i] = new PaymentOption(input);
				}
			}
			if (input.readBoolean()) {
				if (OrderInfo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.savedOrderInfo = new OrderInfo(input);
			}
			if (input.readBoolean()) {
				this.savedCredentials = new SavedCredentials[input.readInt()];
				for (int i = 0; i < this.savedCredentials.length; i++) {
					if (SavedCredentials.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.savedCredentials[i] = new SavedCredentials(input);
				}
			}
			this.canSaveCredentials = input.readBoolean();
			this.needPassword = input.readBoolean();
			if (input.readBoolean()) {
				byte[] productTitleTmp = new byte[input.readInt()];
				input.readFully(productTitleTmp);
				this.productTitle = new String(productTitleTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (FormattedText.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.productDescription = new FormattedText(input);
			}
			if (input.readBoolean()) {
				if (Photo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.productPhoto = new Photo(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PaymentForm.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PaymentForm.CONSTRUCTOR);
			output.writeLong(this.id);
			if (this.invoice == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.invoice.serialize(output);
			}
			output.writeLong(this.sellerBotUserId);
			output.writeLong(this.paymentProviderUserId);
			if (this.paymentProvider == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.paymentProvider.serialize(output);
			}
			if (this.additionalPaymentOptions == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.additionalPaymentOptions.length);
				for (int i = 0; i < this.additionalPaymentOptions.length; i++) {
					this.additionalPaymentOptions[i].serialize(output);
				}
			}
			if (this.savedOrderInfo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.savedOrderInfo.serialize(output);
			}
			if (this.savedCredentials == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.savedCredentials.length);
				for (int i = 0; i < this.savedCredentials.length; i++) {
					this.savedCredentials[i].serialize(output);
				}
			}
			output.writeBoolean(this.canSaveCredentials);
			output.writeBoolean(this.needPassword);
			if (this.productTitle == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] productTitleTmp = this.productTitle.getBytes(StandardCharsets.UTF_8);
				output.writeInt(productTitleTmp.length);
				output.write(productTitleTmp);
			}
			if (this.productDescription == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.productDescription.serialize(output);
			}
			if (this.productPhoto == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.productPhoto.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PaymentForm paymentForm = (PaymentForm) o;
			if (this.id != paymentForm.id) {
				return false;
			}
			if (!Objects.equals(this.invoice, paymentForm.invoice)) {
				return false;
			}
			if (this.sellerBotUserId != paymentForm.sellerBotUserId) {
				return false;
			}
			if (this.paymentProviderUserId != paymentForm.paymentProviderUserId) {
				return false;
			}
			if (!Objects.equals(this.paymentProvider, paymentForm.paymentProvider)) {
				return false;
			}
			if (!Arrays.equals(this.additionalPaymentOptions, paymentForm.additionalPaymentOptions)) {
				return false;
			}
			if (!Objects.equals(this.savedOrderInfo, paymentForm.savedOrderInfo)) {
				return false;
			}
			if (!Arrays.equals(this.savedCredentials, paymentForm.savedCredentials)) {
				return false;
			}
			if (this.canSaveCredentials != paymentForm.canSaveCredentials) {
				return false;
			}
			if (this.needPassword != paymentForm.needPassword) {
				return false;
			}
			if (this.productTitle != paymentForm.productTitle) {
				return false;
			}
			if (!Objects.equals(this.productDescription, paymentForm.productDescription)) {
				return false;
			}
			if (!Objects.equals(this.productPhoto, paymentForm.productPhoto)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.id);
			result = result * 31 + (this.invoice == null ? 0 : this.invoice.hashCode());
			result = result * 31 + (this.paymentProvider == null ? 0 : this.paymentProvider.hashCode());
			result = result * 31 + (Arrays.hashCode(this.additionalPaymentOptions));
			result = result * 31 + (this.savedOrderInfo == null ? 0 : this.savedOrderInfo.hashCode());
			result = result * 31 + (Arrays.hashCode(this.savedCredentials));
			result = result * 31 + (this.productTitle == null ? 0 : this.productTitle.hashCode());
			result = result * 31 + (this.productDescription == null ? 0 : this.productDescription.hashCode());
			result = result * 31 + (this.productPhoto == null ? 0 : this.productPhoto.hashCode());
			return result;
		}
	}

	/**
	 * Describes an additional payment option.
	**/
	public static final class PaymentOption extends Object {


		/**
		 * Title for the payment option.
		**/
		public String title;

		/**
		 * Payment form URL to be opened in a web view.
		**/
		public String url;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -294020965;

		/**
		 * Describes an additional payment option.
		**/
		public PaymentOption() {}

		/**
		 * Describes an additional payment option.
		 *
		 * @param title Title for the payment option.
		 * @param url Payment form URL to be opened in a web view.
		**/
		public PaymentOption(String title, String url) {
			this.title = title;
			this.url = url;
		}

		/**
		 * Describes an additional payment option.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PaymentOption(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] urlTmp = new byte[input.readInt()];
				input.readFully(urlTmp);
				this.url = new String(urlTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PaymentOption.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PaymentOption.CONSTRUCTOR);
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
			if (this.url == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] urlTmp = this.url.getBytes(StandardCharsets.UTF_8);
				output.writeInt(urlTmp.length);
				output.write(urlTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PaymentOption paymentOption = (PaymentOption) o;
			if (this.title != paymentOption.title) {
				return false;
			}
			if (this.url != paymentOption.url) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.title == null ? 0 : this.title.hashCode();
			result = result * 31 + (this.url == null ? 0 : this.url.hashCode());
			return result;
		}
	}

	/**
	 * Smart Glocal payment provider.
	**/
	public static final class PaymentProviderSmartGlocal extends PaymentProvider {


		/**
		 * Public payment token.
		**/
		public String publicToken;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1800479470;

		/**
		 * Smart Glocal payment provider.
		**/
		public PaymentProviderSmartGlocal() {}

		/**
		 * Smart Glocal payment provider.
		 *
		 * @param publicToken Public payment token.
		**/
		public PaymentProviderSmartGlocal(String publicToken) {
			this.publicToken = publicToken;
		}

		/**
		 * Smart Glocal payment provider.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PaymentProviderSmartGlocal(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] publicTokenTmp = new byte[input.readInt()];
				input.readFully(publicTokenTmp);
				this.publicToken = new String(publicTokenTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PaymentProviderSmartGlocal.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PaymentProviderSmartGlocal.CONSTRUCTOR);
			if (this.publicToken == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] publicTokenTmp = this.publicToken.getBytes(StandardCharsets.UTF_8);
				output.writeInt(publicTokenTmp.length);
				output.write(publicTokenTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PaymentProviderSmartGlocal paymentProviderSmartGlocal = (PaymentProviderSmartGlocal) o;
			if (this.publicToken != paymentProviderSmartGlocal.publicToken) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.publicToken == null ? 0 : this.publicToken.hashCode();
		}
	}

	/**
	 * Stripe payment provider.
	**/
	public static final class PaymentProviderStripe extends PaymentProvider {


		/**
		 * Stripe API publishable key.
		**/
		public String publishableKey;

		/**
		 * True, if the user country must be provided.
		**/
		public boolean needCountry;

		/**
		 * True, if the user ZIP/postal code must be provided.
		**/
		public boolean needPostalCode;

		/**
		 * True, if the cardholder name must be provided.
		**/
		public boolean needCardholderName;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 370467227;

		/**
		 * Stripe payment provider.
		**/
		public PaymentProviderStripe() {}

		/**
		 * Stripe payment provider.
		 *
		 * @param publishableKey Stripe API publishable key.
		 * @param needCountry True, if the user country must be provided.
		 * @param needPostalCode True, if the user ZIP/postal code must be provided.
		 * @param needCardholderName True, if the cardholder name must be provided.
		**/
		public PaymentProviderStripe(String publishableKey,
				boolean needCountry,
				boolean needPostalCode,
				boolean needCardholderName) {
			this.publishableKey = publishableKey;
			this.needCountry = needCountry;
			this.needPostalCode = needPostalCode;
			this.needCardholderName = needCardholderName;
		}

		/**
		 * Stripe payment provider.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PaymentProviderStripe(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] publishableKeyTmp = new byte[input.readInt()];
				input.readFully(publishableKeyTmp);
				this.publishableKey = new String(publishableKeyTmp, StandardCharsets.UTF_8);
			}
			this.needCountry = input.readBoolean();
			this.needPostalCode = input.readBoolean();
			this.needCardholderName = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PaymentProviderStripe.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PaymentProviderStripe.CONSTRUCTOR);
			if (this.publishableKey == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] publishableKeyTmp = this.publishableKey.getBytes(StandardCharsets.UTF_8);
				output.writeInt(publishableKeyTmp.length);
				output.write(publishableKeyTmp);
			}
			output.writeBoolean(this.needCountry);
			output.writeBoolean(this.needPostalCode);
			output.writeBoolean(this.needCardholderName);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PaymentProviderStripe paymentProviderStripe = (PaymentProviderStripe) o;
			if (this.publishableKey != paymentProviderStripe.publishableKey) {
				return false;
			}
			if (this.needCountry != paymentProviderStripe.needCountry) {
				return false;
			}
			if (this.needPostalCode != paymentProviderStripe.needPostalCode) {
				return false;
			}
			if (this.needCardholderName != paymentProviderStripe.needCardholderName) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.needCountry);
			result = result * 31 + (this.publishableKey == null ? 0 : this.publishableKey.hashCode());
			return result;
		}
	}

	/**
	 * Some other payment provider, for which a web payment form must be
	 * shown.
	**/
	public static final class PaymentProviderOther extends PaymentProvider {


		/**
		 * Payment form URL.
		**/
		public String url;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1336876828;

		/**
		 * Some other payment provider, for which a web payment form must be shown.
		**/
		public PaymentProviderOther() {}

		/**
		 * Some other payment provider, for which a web payment form must be shown.
		 *
		 * @param url Payment form URL.
		**/
		public PaymentProviderOther(String url) {
			this.url = url;
		}

		/**
		 * Some other payment provider, for which a web payment form must be shown.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PaymentProviderOther(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] urlTmp = new byte[input.readInt()];
				input.readFully(urlTmp);
				this.url = new String(urlTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PaymentProviderOther.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PaymentProviderOther.CONSTRUCTOR);
			if (this.url == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] urlTmp = this.url.getBytes(StandardCharsets.UTF_8);
				output.writeInt(urlTmp.length);
				output.write(urlTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PaymentProviderOther paymentProviderOther = (PaymentProviderOther) o;
			if (this.url != paymentProviderOther.url) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.url == null ? 0 : this.url.hashCode();
		}
	}

	/**
	 * Contains information about a successful payment.
	**/
	public static final class PaymentReceipt extends Object {


		/**
		 * Product title.
		**/
		public String title;

		/**
		 * Product description.
		**/
		public FormattedText description;

		/**
		 * Product photo; may be null.
		**/
		public Photo photo;

		/**
		 * Point in time (Unix timestamp) when the payment was made.
		**/
		public int date;

		/**
		 * User identifier of the seller bot.
		**/
		public long sellerBotUserId;

		/**
		 * User identifier of the payment provider bot.
		**/
		public long paymentProviderUserId;

		/**
		 * Information about the invoice.
		**/
		public Invoice invoice;

		/**
		 * Order information; may be null.
		**/
		public OrderInfo orderInfo;

		/**
		 * Chosen shipping option; may be null.
		**/
		public ShippingOption shippingOption;

		/**
		 * Title of the saved credentials chosen by the buyer.
		**/
		public String credentialsTitle;

		/**
		 * The amount of tip chosen by the buyer in the smallest units of the currency.
		**/
		public long tipAmount;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -400955711;

		/**
		 * Contains information about a successful payment.
		**/
		public PaymentReceipt() {}

		/**
		 * Contains information about a successful payment.
		 *
		 * @param title Product title.
		 * @param description Product description.
		 * @param photo Product photo; may be null.
		 * @param date Point in time (Unix timestamp) when the payment was made.
		 * @param sellerBotUserId User identifier of the seller bot.
		 * @param paymentProviderUserId User identifier of the payment provider bot.
		 * @param invoice Information about the invoice.
		 * @param orderInfo Order information; may be null.
		 * @param shippingOption Chosen shipping option; may be null.
		 * @param credentialsTitle Title of the saved credentials chosen by the buyer.
		 * @param tipAmount The amount of tip chosen by the buyer in the smallest units of the currency.
		**/
		public PaymentReceipt(String title,
				FormattedText description,
				Photo photo,
				int date,
				long sellerBotUserId,
				long paymentProviderUserId,
				Invoice invoice,
				OrderInfo orderInfo,
				ShippingOption shippingOption,
				String credentialsTitle,
				long tipAmount) {
			this.title = title;
			this.description = description;
			this.photo = photo;
			this.date = date;
			this.sellerBotUserId = sellerBotUserId;
			this.paymentProviderUserId = paymentProviderUserId;
			this.invoice = invoice;
			this.orderInfo = orderInfo;
			this.shippingOption = shippingOption;
			this.credentialsTitle = credentialsTitle;
			this.tipAmount = tipAmount;
		}

		/**
		 * Contains information about a successful payment.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PaymentReceipt(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (FormattedText.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.description = new FormattedText(input);
			}
			if (input.readBoolean()) {
				if (Photo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.photo = new Photo(input);
			}
			this.date = input.readInt();
			this.sellerBotUserId = input.readLong();
			this.paymentProviderUserId = input.readLong();
			if (input.readBoolean()) {
				if (Invoice.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.invoice = new Invoice(input);
			}
			if (input.readBoolean()) {
				if (OrderInfo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.orderInfo = new OrderInfo(input);
			}
			if (input.readBoolean()) {
				if (ShippingOption.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.shippingOption = new ShippingOption(input);
			}
			if (input.readBoolean()) {
				byte[] credentialsTitleTmp = new byte[input.readInt()];
				input.readFully(credentialsTitleTmp);
				this.credentialsTitle = new String(credentialsTitleTmp, StandardCharsets.UTF_8);
			}
			this.tipAmount = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PaymentReceipt.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PaymentReceipt.CONSTRUCTOR);
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
			if (this.description == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.description.serialize(output);
			}
			if (this.photo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.photo.serialize(output);
			}
			output.writeInt(this.date);
			output.writeLong(this.sellerBotUserId);
			output.writeLong(this.paymentProviderUserId);
			if (this.invoice == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.invoice.serialize(output);
			}
			if (this.orderInfo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.orderInfo.serialize(output);
			}
			if (this.shippingOption == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.shippingOption.serialize(output);
			}
			if (this.credentialsTitle == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] credentialsTitleTmp = this.credentialsTitle.getBytes(StandardCharsets.UTF_8);
				output.writeInt(credentialsTitleTmp.length);
				output.write(credentialsTitleTmp);
			}
			output.writeLong(this.tipAmount);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PaymentReceipt paymentReceipt = (PaymentReceipt) o;
			if (this.title != paymentReceipt.title) {
				return false;
			}
			if (!Objects.equals(this.description, paymentReceipt.description)) {
				return false;
			}
			if (!Objects.equals(this.photo, paymentReceipt.photo)) {
				return false;
			}
			if (this.date != paymentReceipt.date) {
				return false;
			}
			if (this.sellerBotUserId != paymentReceipt.sellerBotUserId) {
				return false;
			}
			if (this.paymentProviderUserId != paymentReceipt.paymentProviderUserId) {
				return false;
			}
			if (!Objects.equals(this.invoice, paymentReceipt.invoice)) {
				return false;
			}
			if (!Objects.equals(this.orderInfo, paymentReceipt.orderInfo)) {
				return false;
			}
			if (!Objects.equals(this.shippingOption, paymentReceipt.shippingOption)) {
				return false;
			}
			if (this.credentialsTitle != paymentReceipt.credentialsTitle) {
				return false;
			}
			if (this.tipAmount != paymentReceipt.tipAmount) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.date);
			result = result * 31 + (this.title == null ? 0 : this.title.hashCode());
			result = result * 31 + (this.description == null ? 0 : this.description.hashCode());
			result = result * 31 + (this.photo == null ? 0 : this.photo.hashCode());
			result = result * 31 + (this.invoice == null ? 0 : this.invoice.hashCode());
			result = result * 31 + (this.orderInfo == null ? 0 : this.orderInfo.hashCode());
			result = result * 31 + (this.shippingOption == null ? 0 : this.shippingOption.hashCode());
			result = result * 31 + (this.credentialsTitle == null ? 0 : this.credentialsTitle.hashCode());
			return result;
		}
	}

	/**
	 * Contains the result of a payment request.
	**/
	public static final class PaymentResult extends Object {


		/**
		 * True, if the payment request was successful; otherwise, the verificationUrl will be non-empty.
		**/
		public boolean success;

		/**
		 * URL for additional payment credentials verification.
		**/
		public String verificationUrl;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -804263843;

		/**
		 * Contains the result of a payment request.
		**/
		public PaymentResult() {}

		/**
		 * Contains the result of a payment request.
		 *
		 * @param success True, if the payment request was successful; otherwise, the verificationUrl will be non-empty.
		 * @param verificationUrl URL for additional payment credentials verification.
		**/
		public PaymentResult(boolean success, String verificationUrl) {
			this.success = success;
			this.verificationUrl = verificationUrl;
		}

		/**
		 * Contains the result of a payment request.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PaymentResult(DataInput input) throws IOException {
			this.success = input.readBoolean();
			if (input.readBoolean()) {
				byte[] verificationUrlTmp = new byte[input.readInt()];
				input.readFully(verificationUrlTmp);
				this.verificationUrl = new String(verificationUrlTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PaymentResult.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PaymentResult.CONSTRUCTOR);
			output.writeBoolean(this.success);
			if (this.verificationUrl == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] verificationUrlTmp = this.verificationUrl.getBytes(StandardCharsets.UTF_8);
				output.writeInt(verificationUrlTmp.length);
				output.write(verificationUrlTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PaymentResult paymentResult = (PaymentResult) o;
			if (this.success != paymentResult.success) {
				return false;
			}
			if (this.verificationUrl != paymentResult.verificationUrl) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.success);
			result = result * 31 + (this.verificationUrl == null ? 0 : this.verificationUrl.hashCode());
			return result;
		}
	}

	/**
	 * Contains the user&#039;s personal details.
	**/
	public static final class PersonalDetails extends Object {


		/**
		 * First name of the user written in English; 1-255 characters.
		**/
		public String firstName;

		/**
		 * Middle name of the user written in English; 0-255 characters.
		**/
		public String middleName;

		/**
		 * Last name of the user written in English; 1-255 characters.
		**/
		public String lastName;

		/**
		 * Native first name of the user; 1-255 characters.
		**/
		public String nativeFirstName;

		/**
		 * Native middle name of the user; 0-255 characters.
		**/
		public String nativeMiddleName;

		/**
		 * Native last name of the user; 1-255 characters.
		**/
		public String nativeLastName;

		/**
		 * Birthdate of the user.
		**/
		public Date birthdate;

		/**
		 * Gender of the user, &quot;male&quot; or &quot;female&quot;.
		**/
		public String gender;

		/**
		 * A two-letter ISO 3166-1 alpha-2 country code of the user&#039;s country.
		**/
		public String countryCode;

		/**
		 * A two-letter ISO 3166-1 alpha-2 country code of the user&#039;s residence country.
		**/
		public String residenceCountryCode;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1061656137;

		/**
		 * Contains the user&#039;s personal details.
		**/
		public PersonalDetails() {}

		/**
		 * Contains the user&#039;s personal details.
		 *
		 * @param firstName First name of the user written in English; 1-255 characters.
		 * @param middleName Middle name of the user written in English; 0-255 characters.
		 * @param lastName Last name of the user written in English; 1-255 characters.
		 * @param nativeFirstName Native first name of the user; 1-255 characters.
		 * @param nativeMiddleName Native middle name of the user; 0-255 characters.
		 * @param nativeLastName Native last name of the user; 1-255 characters.
		 * @param birthdate Birthdate of the user.
		 * @param gender Gender of the user, &quot;male&quot; or &quot;female&quot;.
		 * @param countryCode A two-letter ISO 3166-1 alpha-2 country code of the user&#039;s country.
		 * @param residenceCountryCode A two-letter ISO 3166-1 alpha-2 country code of the user&#039;s residence country.
		**/
		public PersonalDetails(String firstName,
				String middleName,
				String lastName,
				String nativeFirstName,
				String nativeMiddleName,
				String nativeLastName,
				Date birthdate,
				String gender,
				String countryCode,
				String residenceCountryCode) {
			this.firstName = firstName;
			this.middleName = middleName;
			this.lastName = lastName;
			this.nativeFirstName = nativeFirstName;
			this.nativeMiddleName = nativeMiddleName;
			this.nativeLastName = nativeLastName;
			this.birthdate = birthdate;
			this.gender = gender;
			this.countryCode = countryCode;
			this.residenceCountryCode = residenceCountryCode;
		}

		/**
		 * Contains the user&#039;s personal details.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PersonalDetails(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] firstNameTmp = new byte[input.readInt()];
				input.readFully(firstNameTmp);
				this.firstName = new String(firstNameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] middleNameTmp = new byte[input.readInt()];
				input.readFully(middleNameTmp);
				this.middleName = new String(middleNameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] lastNameTmp = new byte[input.readInt()];
				input.readFully(lastNameTmp);
				this.lastName = new String(lastNameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] nativeFirstNameTmp = new byte[input.readInt()];
				input.readFully(nativeFirstNameTmp);
				this.nativeFirstName = new String(nativeFirstNameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] nativeMiddleNameTmp = new byte[input.readInt()];
				input.readFully(nativeMiddleNameTmp);
				this.nativeMiddleName = new String(nativeMiddleNameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] nativeLastNameTmp = new byte[input.readInt()];
				input.readFully(nativeLastNameTmp);
				this.nativeLastName = new String(nativeLastNameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (Date.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.birthdate = new Date(input);
			}
			if (input.readBoolean()) {
				byte[] genderTmp = new byte[input.readInt()];
				input.readFully(genderTmp);
				this.gender = new String(genderTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] countryCodeTmp = new byte[input.readInt()];
				input.readFully(countryCodeTmp);
				this.countryCode = new String(countryCodeTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] residenceCountryCodeTmp = new byte[input.readInt()];
				input.readFully(residenceCountryCodeTmp);
				this.residenceCountryCode = new String(residenceCountryCodeTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PersonalDetails.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PersonalDetails.CONSTRUCTOR);
			if (this.firstName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] firstNameTmp = this.firstName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(firstNameTmp.length);
				output.write(firstNameTmp);
			}
			if (this.middleName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] middleNameTmp = this.middleName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(middleNameTmp.length);
				output.write(middleNameTmp);
			}
			if (this.lastName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] lastNameTmp = this.lastName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(lastNameTmp.length);
				output.write(lastNameTmp);
			}
			if (this.nativeFirstName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nativeFirstNameTmp = this.nativeFirstName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nativeFirstNameTmp.length);
				output.write(nativeFirstNameTmp);
			}
			if (this.nativeMiddleName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nativeMiddleNameTmp = this.nativeMiddleName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nativeMiddleNameTmp.length);
				output.write(nativeMiddleNameTmp);
			}
			if (this.nativeLastName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nativeLastNameTmp = this.nativeLastName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nativeLastNameTmp.length);
				output.write(nativeLastNameTmp);
			}
			if (this.birthdate == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.birthdate.serialize(output);
			}
			if (this.gender == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] genderTmp = this.gender.getBytes(StandardCharsets.UTF_8);
				output.writeInt(genderTmp.length);
				output.write(genderTmp);
			}
			if (this.countryCode == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] countryCodeTmp = this.countryCode.getBytes(StandardCharsets.UTF_8);
				output.writeInt(countryCodeTmp.length);
				output.write(countryCodeTmp);
			}
			if (this.residenceCountryCode == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] residenceCountryCodeTmp = this.residenceCountryCode.getBytes(StandardCharsets.UTF_8);
				output.writeInt(residenceCountryCodeTmp.length);
				output.write(residenceCountryCodeTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PersonalDetails personalDetails = (PersonalDetails) o;
			if (this.firstName != personalDetails.firstName) {
				return false;
			}
			if (this.middleName != personalDetails.middleName) {
				return false;
			}
			if (this.lastName != personalDetails.lastName) {
				return false;
			}
			if (this.nativeFirstName != personalDetails.nativeFirstName) {
				return false;
			}
			if (this.nativeMiddleName != personalDetails.nativeMiddleName) {
				return false;
			}
			if (this.nativeLastName != personalDetails.nativeLastName) {
				return false;
			}
			if (!Objects.equals(this.birthdate, personalDetails.birthdate)) {
				return false;
			}
			if (this.gender != personalDetails.gender) {
				return false;
			}
			if (this.countryCode != personalDetails.countryCode) {
				return false;
			}
			if (this.residenceCountryCode != personalDetails.residenceCountryCode) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.firstName == null ? 0 : this.firstName.hashCode();
			result = result * 31 + (this.middleName == null ? 0 : this.middleName.hashCode());
			result = result * 31 + (this.lastName == null ? 0 : this.lastName.hashCode());
			result = result * 31 + (this.nativeFirstName == null ? 0 : this.nativeFirstName.hashCode());
			result = result * 31 + (this.nativeMiddleName == null ? 0 : this.nativeMiddleName.hashCode());
			result = result * 31 + (this.nativeLastName == null ? 0 : this.nativeLastName.hashCode());
			result = result * 31 + (this.birthdate == null ? 0 : this.birthdate.hashCode());
			result = result * 31 + (this.gender == null ? 0 : this.gender.hashCode());
			result = result * 31 + (this.countryCode == null ? 0 : this.countryCode.hashCode());
			result = result * 31 + (this.residenceCountryCode == null ? 0 : this.residenceCountryCode.hashCode());
			return result;
		}
	}

	/**
	 * A personal document, containing some information about a user.
	**/
	public static final class PersonalDocument extends Object {


		/**
		 * List of files containing the pages of the document.
		**/
		public DatedFile[] files;

		/**
		 * List of files containing a certified English translation of the document.
		**/
		public DatedFile[] translation;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1011634661;

		/**
		 * A personal document, containing some information about a user.
		**/
		public PersonalDocument() {}

		/**
		 * A personal document, containing some information about a user.
		 *
		 * @param files List of files containing the pages of the document.
		 * @param translation List of files containing a certified English translation of the document.
		**/
		public PersonalDocument(DatedFile[] files, DatedFile[] translation) {
			this.files = files;
			this.translation = translation;
		}

		/**
		 * A personal document, containing some information about a user.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PersonalDocument(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.files = new DatedFile[input.readInt()];
				for (int i = 0; i < this.files.length; i++) {
					if (DatedFile.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.files[i] = new DatedFile(input);
				}
			}
			if (input.readBoolean()) {
				this.translation = new DatedFile[input.readInt()];
				for (int i = 0; i < this.translation.length; i++) {
					if (DatedFile.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.translation[i] = new DatedFile(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PersonalDocument.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PersonalDocument.CONSTRUCTOR);
			if (this.files == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.files.length);
				for (int i = 0; i < this.files.length; i++) {
					this.files[i].serialize(output);
				}
			}
			if (this.translation == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.translation.length);
				for (int i = 0; i < this.translation.length; i++) {
					this.translation[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PersonalDocument personalDocument = (PersonalDocument) o;
			if (!Arrays.equals(this.files, personalDocument.files)) {
				return false;
			}
			if (!Arrays.equals(this.translation, personalDocument.translation)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Arrays.hashCode(this.files);
			result = result * 31 + (Arrays.hashCode(this.translation));
			return result;
		}
	}

	/**
	 * Contains settings for the authentication of the user&#039;s phone
	 * number.
	**/
	public static final class PhoneNumberAuthenticationSettings extends Object {


		/**
		 * Pass true if the authentication code may be sent via a flash call to the specified phone number.
		**/
		public boolean allowFlashCall;

		/**
		 * Pass true if the authentication code may be sent via a missed call to the specified phone number.
		**/
		public boolean allowMissedCall;

		/**
		 * Pass true if the authenticated phone number is used on the current device.
		**/
		public boolean isCurrentPhoneNumber;

		/**
		 * For official applications only. True, if the application can use Android SMS Retriever API (requires Google Play Services &gt;= 10.2) to automatically receive the authentication code from the SMS. See https://developers.google.com/identity/sms-retriever/ for more details.
		**/
		public boolean allowSmsRetrieverApi;

		/**
		 * For official Android and iOS applications only; pass null otherwise. Settings for Firebase Authentication.
		**/
		public FirebaseAuthenticationSettings firebaseAuthenticationSettings;

		/**
		 * List of up to 20 authentication tokens, recently received in updateOption(&quot;authentication_token&quot;) in previously logged out sessions.
		**/
		public String[] authenticationTokens;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -493266762;

		/**
		 * Contains settings for the authentication of the user&#039;s phone number.
		**/
		public PhoneNumberAuthenticationSettings() {}

		/**
		 * Contains settings for the authentication of the user&#039;s phone number.
		 *
		 * @param allowFlashCall Pass true if the authentication code may be sent via a flash call to the specified phone number.
		 * @param allowMissedCall Pass true if the authentication code may be sent via a missed call to the specified phone number.
		 * @param isCurrentPhoneNumber Pass true if the authenticated phone number is used on the current device.
		 * @param allowSmsRetrieverApi For official applications only. True, if the application can use Android SMS Retriever API (requires Google Play Services &gt;= 10.2) to automatically receive the authentication code from the SMS. See https://developers.google.com/identity/sms-retriever/ for more details.
		 * @param firebaseAuthenticationSettings For official Android and iOS applications only; pass null otherwise. Settings for Firebase Authentication.
		 * @param authenticationTokens List of up to 20 authentication tokens, recently received in updateOption(&quot;authentication_token&quot;) in previously logged out sessions.
		**/
		public PhoneNumberAuthenticationSettings(boolean allowFlashCall,
				boolean allowMissedCall,
				boolean isCurrentPhoneNumber,
				boolean allowSmsRetrieverApi,
				FirebaseAuthenticationSettings firebaseAuthenticationSettings,
				String[] authenticationTokens) {
			this.allowFlashCall = allowFlashCall;
			this.allowMissedCall = allowMissedCall;
			this.isCurrentPhoneNumber = isCurrentPhoneNumber;
			this.allowSmsRetrieverApi = allowSmsRetrieverApi;
			this.firebaseAuthenticationSettings = firebaseAuthenticationSettings;
			this.authenticationTokens = authenticationTokens;
		}

		/**
		 * Contains settings for the authentication of the user&#039;s phone number.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PhoneNumberAuthenticationSettings(DataInput input) throws IOException {
			this.allowFlashCall = input.readBoolean();
			this.allowMissedCall = input.readBoolean();
			this.isCurrentPhoneNumber = input.readBoolean();
			this.allowSmsRetrieverApi = input.readBoolean();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case FirebaseAuthenticationSettingsAndroid.CONSTRUCTOR: this.firebaseAuthenticationSettings = new FirebaseAuthenticationSettingsAndroid(input); break;
					case FirebaseAuthenticationSettingsIos.CONSTRUCTOR: this.firebaseAuthenticationSettings = new FirebaseAuthenticationSettingsIos(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				this.authenticationTokens = new String[input.readInt()];
				for (int i = 0; i < this.authenticationTokens.length; i++) {
					byte[] authenticationTokensTmp = new byte[input.readInt()];
					input.readFully(authenticationTokensTmp);
					this.authenticationTokens[i] = new String(authenticationTokensTmp, StandardCharsets.UTF_8);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PhoneNumberAuthenticationSettings.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PhoneNumberAuthenticationSettings.CONSTRUCTOR);
			output.writeBoolean(this.allowFlashCall);
			output.writeBoolean(this.allowMissedCall);
			output.writeBoolean(this.isCurrentPhoneNumber);
			output.writeBoolean(this.allowSmsRetrieverApi);
			if (this.firebaseAuthenticationSettings == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.firebaseAuthenticationSettings.serialize(output);
			}
			if (this.authenticationTokens == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.authenticationTokens.length);
				for (int i = 0; i < this.authenticationTokens.length; i++) {
					byte[] authenticationTokensTmp = this.authenticationTokens[i].getBytes(StandardCharsets.UTF_8);
					output.writeInt(authenticationTokensTmp.length);
					output.write(authenticationTokensTmp);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PhoneNumberAuthenticationSettings phoneNumberAuthenticationSettings = (PhoneNumberAuthenticationSettings) o;
			if (this.allowFlashCall != phoneNumberAuthenticationSettings.allowFlashCall) {
				return false;
			}
			if (this.allowMissedCall != phoneNumberAuthenticationSettings.allowMissedCall) {
				return false;
			}
			if (this.isCurrentPhoneNumber != phoneNumberAuthenticationSettings.isCurrentPhoneNumber) {
				return false;
			}
			if (this.allowSmsRetrieverApi != phoneNumberAuthenticationSettings.allowSmsRetrieverApi) {
				return false;
			}
			if (!Objects.equals(this.firebaseAuthenticationSettings, phoneNumberAuthenticationSettings.firebaseAuthenticationSettings)) {
				return false;
			}
			if (!Arrays.equals(this.authenticationTokens, phoneNumberAuthenticationSettings.authenticationTokens)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.allowFlashCall);
			result = result * 31 + (this.firebaseAuthenticationSettings == null ? 0 : this.firebaseAuthenticationSettings.hashCode());
			result = result * 31 + (Arrays.hashCode(this.authenticationTokens));
			return result;
		}
	}

	/**
	 * Contains information about a phone number.
	**/
	public static final class PhoneNumberInfo extends Object {


		/**
		 * Information about the country to which the phone number belongs; may be null.
		**/
		public CountryInfo country;

		/**
		 * The part of the phone number denoting country calling code or its part.
		**/
		public String countryCallingCode;

		/**
		 * The phone number without country calling code formatted accordingly to local rules. Expected digits are returned as &#039;-&#039;, but even more digits might be entered by the user.
		**/
		public String formattedPhoneNumber;

		/**
		 * True, if the phone number was bought on Fragment and isn&#039;t tied to a SIM card.
		**/
		public boolean isAnonymous;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -758933343;

		/**
		 * Contains information about a phone number.
		**/
		public PhoneNumberInfo() {}

		/**
		 * Contains information about a phone number.
		 *
		 * @param country Information about the country to which the phone number belongs; may be null.
		 * @param countryCallingCode The part of the phone number denoting country calling code or its part.
		 * @param formattedPhoneNumber The phone number without country calling code formatted accordingly to local rules. Expected digits are returned as &#039;-&#039;, but even more digits might be entered by the user.
		 * @param isAnonymous True, if the phone number was bought on Fragment and isn&#039;t tied to a SIM card.
		**/
		public PhoneNumberInfo(CountryInfo country,
				String countryCallingCode,
				String formattedPhoneNumber,
				boolean isAnonymous) {
			this.country = country;
			this.countryCallingCode = countryCallingCode;
			this.formattedPhoneNumber = formattedPhoneNumber;
			this.isAnonymous = isAnonymous;
		}

		/**
		 * Contains information about a phone number.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PhoneNumberInfo(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (CountryInfo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.country = new CountryInfo(input);
			}
			if (input.readBoolean()) {
				byte[] countryCallingCodeTmp = new byte[input.readInt()];
				input.readFully(countryCallingCodeTmp);
				this.countryCallingCode = new String(countryCallingCodeTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] formattedPhoneNumberTmp = new byte[input.readInt()];
				input.readFully(formattedPhoneNumberTmp);
				this.formattedPhoneNumber = new String(formattedPhoneNumberTmp, StandardCharsets.UTF_8);
			}
			this.isAnonymous = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PhoneNumberInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PhoneNumberInfo.CONSTRUCTOR);
			if (this.country == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.country.serialize(output);
			}
			if (this.countryCallingCode == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] countryCallingCodeTmp = this.countryCallingCode.getBytes(StandardCharsets.UTF_8);
				output.writeInt(countryCallingCodeTmp.length);
				output.write(countryCallingCodeTmp);
			}
			if (this.formattedPhoneNumber == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] formattedPhoneNumberTmp = this.formattedPhoneNumber.getBytes(StandardCharsets.UTF_8);
				output.writeInt(formattedPhoneNumberTmp.length);
				output.write(formattedPhoneNumberTmp);
			}
			output.writeBoolean(this.isAnonymous);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PhoneNumberInfo phoneNumberInfo = (PhoneNumberInfo) o;
			if (!Objects.equals(this.country, phoneNumberInfo.country)) {
				return false;
			}
			if (this.countryCallingCode != phoneNumberInfo.countryCallingCode) {
				return false;
			}
			if (this.formattedPhoneNumber != phoneNumberInfo.formattedPhoneNumber) {
				return false;
			}
			if (this.isAnonymous != phoneNumberInfo.isAnonymous) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isAnonymous);
			result = result * 31 + (this.country == null ? 0 : this.country.hashCode());
			result = result * 31 + (this.countryCallingCode == null ? 0 : this.countryCallingCode.hashCode());
			result = result * 31 + (this.formattedPhoneNumber == null ? 0 : this.formattedPhoneNumber.hashCode());
			return result;
		}
	}

	/**
	 * Describes a photo.
	**/
	public static final class Photo extends Object {


		/**
		 * True, if stickers were added to the photo. The list of corresponding sticker sets can be received using getAttachedStickerSets.
		**/
		public boolean hasStickers;

		/**
		 * Photo minithumbnail; may be null.
		**/
		public Minithumbnail minithumbnail;

		/**
		 * Available variants of the photo, in different sizes.
		**/
		public PhotoSize[] sizes;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2022871583;

		/**
		 * Describes a photo.
		**/
		public Photo() {}

		/**
		 * Describes a photo.
		 *
		 * @param hasStickers True, if stickers were added to the photo. The list of corresponding sticker sets can be received using getAttachedStickerSets.
		 * @param minithumbnail Photo minithumbnail; may be null.
		 * @param sizes Available variants of the photo, in different sizes.
		**/
		public Photo(boolean hasStickers,
				Minithumbnail minithumbnail,
				PhotoSize[] sizes) {
			this.hasStickers = hasStickers;
			this.minithumbnail = minithumbnail;
			this.sizes = sizes;
		}

		/**
		 * Describes a photo.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public Photo(DataInput input) throws IOException {
			this.hasStickers = input.readBoolean();
			if (input.readBoolean()) {
				if (Minithumbnail.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.minithumbnail = new Minithumbnail(input);
			}
			if (input.readBoolean()) {
				this.sizes = new PhotoSize[input.readInt()];
				for (int i = 0; i < this.sizes.length; i++) {
					if (PhotoSize.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.sizes[i] = new PhotoSize(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return Photo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(Photo.CONSTRUCTOR);
			output.writeBoolean(this.hasStickers);
			if (this.minithumbnail == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.minithumbnail.serialize(output);
			}
			if (this.sizes == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.sizes.length);
				for (int i = 0; i < this.sizes.length; i++) {
					this.sizes[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			Photo photo = (Photo) o;
			if (this.hasStickers != photo.hasStickers) {
				return false;
			}
			if (!Objects.equals(this.minithumbnail, photo.minithumbnail)) {
				return false;
			}
			if (!Arrays.equals(this.sizes, photo.sizes)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.hasStickers);
			result = result * 31 + (this.minithumbnail == null ? 0 : this.minithumbnail.hashCode());
			result = result * 31 + (Arrays.hashCode(this.sizes));
			return result;
		}
	}

	/**
	 * Describes an image in JPEG format.
	**/
	public static final class PhotoSize extends Object {


		/**
		 * Image type (see https://core.telegram.org/constructor/photoSize).
		**/
		public String type;

		/**
		 * Information about the image file.
		**/
		public File photo;

		/**
		 * Image width.
		**/
		public int width;

		/**
		 * Image height.
		**/
		public int height;

		/**
		 * Sizes of progressive JPEG file prefixes, which can be used to preliminarily show the image; in bytes.
		**/
		public int[] progressiveSizes;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1609182352;

		/**
		 * Describes an image in JPEG format.
		**/
		public PhotoSize() {}

		/**
		 * Describes an image in JPEG format.
		 *
		 * @param type Image type (see https://core.telegram.org/constructor/photoSize).
		 * @param photo Information about the image file.
		 * @param width Image width.
		 * @param height Image height.
		 * @param progressiveSizes Sizes of progressive JPEG file prefixes, which can be used to preliminarily show the image; in bytes.
		**/
		public PhotoSize(String type,
				File photo,
				int width,
				int height,
				int[] progressiveSizes) {
			this.type = type;
			this.photo = photo;
			this.width = width;
			this.height = height;
			this.progressiveSizes = progressiveSizes;
		}

		/**
		 * Describes an image in JPEG format.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PhotoSize(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] typeTmp = new byte[input.readInt()];
				input.readFully(typeTmp);
				this.type = new String(typeTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (File.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.photo = new File(input);
			}
			this.width = input.readInt();
			this.height = input.readInt();
			if (input.readBoolean()) {
				this.progressiveSizes = new int[input.readInt()];
				for (int i = 0; i < this.progressiveSizes.length; i++) {
					this.progressiveSizes[i] = input.readInt();
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PhotoSize.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PhotoSize.CONSTRUCTOR);
			if (this.type == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] typeTmp = this.type.getBytes(StandardCharsets.UTF_8);
				output.writeInt(typeTmp.length);
				output.write(typeTmp);
			}
			if (this.photo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.photo.serialize(output);
			}
			output.writeInt(this.width);
			output.writeInt(this.height);
			if (this.progressiveSizes == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.progressiveSizes.length);
				for (int i = 0; i < this.progressiveSizes.length; i++) {
					output.writeInt(this.progressiveSizes[i]);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PhotoSize photoSize = (PhotoSize) o;
			if (this.type != photoSize.type) {
				return false;
			}
			if (!Objects.equals(this.photo, photoSize.photo)) {
				return false;
			}
			if (this.width != photoSize.width) {
				return false;
			}
			if (this.height != photoSize.height) {
				return false;
			}
			if (!Arrays.equals(this.progressiveSizes, photoSize.progressiveSizes)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.width);
			result = result * 31 + (this.type == null ? 0 : this.type.hashCode());
			result = result * 31 + (this.photo == null ? 0 : this.photo.hashCode());
			result = result * 31 + (Arrays.hashCode(this.progressiveSizes));
			return result;
		}
	}

	/**
	 * A point on a Cartesian plane.
	**/
	public static final class Point extends Object {


		/**
		 * The point&#039;s first coordinate.
		**/
		public double x;

		/**
		 * The point&#039;s second coordinate.
		**/
		public double y;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 437515705;

		/**
		 * A point on a Cartesian plane.
		**/
		public Point() {}

		/**
		 * A point on a Cartesian plane.
		 *
		 * @param x The point&#039;s first coordinate.
		 * @param y The point&#039;s second coordinate.
		**/
		public Point(double x, double y) {
			this.x = x;
			this.y = y;
		}

		/**
		 * A point on a Cartesian plane.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public Point(DataInput input) throws IOException {
			this.x = input.readDouble();
			this.y = input.readDouble();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return Point.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(Point.CONSTRUCTOR);
			output.writeDouble(this.x);
			output.writeDouble(this.y);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			Point point = (Point) o;
			if (this.x != point.x) {
				return false;
			}
			if (this.y != point.y) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Double.hashCode(this.x);
			return result;
		}
	}

	/**
	 * Describes a poll.
	**/
	public static final class Poll extends Object {


		/**
		 * Unique poll identifier.
		**/
		public long id;

		/**
		 * Poll question; 1-300 characters.
		**/
		public String question;

		/**
		 * List of poll answer options.
		**/
		public PollOption[] options;

		/**
		 * Total number of voters, participating in the poll.
		**/
		public int totalVoterCount;

		/**
		 * User identifiers of recent voters, if the poll is non-anonymous.
		**/
		public long[] recentVoterUserIds;

		/**
		 * True, if the poll is anonymous.
		**/
		public boolean isAnonymous;

		/**
		 * Type of the poll.
		**/
		public PollType type;

		/**
		 * Amount of time the poll will be active after creation, in seconds.
		**/
		public int openPeriod;

		/**
		 * Point in time (Unix timestamp) when the poll will automatically be closed.
		**/
		public int closeDate;

		/**
		 * True, if the poll is closed.
		**/
		public boolean isClosed;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 116940085;

		/**
		 * Describes a poll.
		**/
		public Poll() {}

		/**
		 * Describes a poll.
		 *
		 * @param id Unique poll identifier.
		 * @param question Poll question; 1-300 characters.
		 * @param options List of poll answer options.
		 * @param totalVoterCount Total number of voters, participating in the poll.
		 * @param recentVoterUserIds User identifiers of recent voters, if the poll is non-anonymous.
		 * @param isAnonymous True, if the poll is anonymous.
		 * @param type Type of the poll.
		 * @param openPeriod Amount of time the poll will be active after creation, in seconds.
		 * @param closeDate Point in time (Unix timestamp) when the poll will automatically be closed.
		 * @param isClosed True, if the poll is closed.
		**/
		public Poll(long id,
				String question,
				PollOption[] options,
				int totalVoterCount,
				long[] recentVoterUserIds,
				boolean isAnonymous,
				PollType type,
				int openPeriod,
				int closeDate,
				boolean isClosed) {
			this.id = id;
			this.question = question;
			this.options = options;
			this.totalVoterCount = totalVoterCount;
			this.recentVoterUserIds = recentVoterUserIds;
			this.isAnonymous = isAnonymous;
			this.type = type;
			this.openPeriod = openPeriod;
			this.closeDate = closeDate;
			this.isClosed = isClosed;
		}

		/**
		 * Describes a poll.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public Poll(DataInput input) throws IOException {
			this.id = input.readLong();
			if (input.readBoolean()) {
				byte[] questionTmp = new byte[input.readInt()];
				input.readFully(questionTmp);
				this.question = new String(questionTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				this.options = new PollOption[input.readInt()];
				for (int i = 0; i < this.options.length; i++) {
					if (PollOption.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.options[i] = new PollOption(input);
				}
			}
			this.totalVoterCount = input.readInt();
			if (input.readBoolean()) {
				this.recentVoterUserIds = new long[input.readInt()];
				for (int i = 0; i < this.recentVoterUserIds.length; i++) {
					this.recentVoterUserIds[i] = input.readLong();
				}
			}
			this.isAnonymous = input.readBoolean();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case PollTypeRegular.CONSTRUCTOR: this.type = new PollTypeRegular(input); break;
					case PollTypeQuiz.CONSTRUCTOR: this.type = new PollTypeQuiz(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.openPeriod = input.readInt();
			this.closeDate = input.readInt();
			this.isClosed = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return Poll.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(Poll.CONSTRUCTOR);
			output.writeLong(this.id);
			if (this.question == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] questionTmp = this.question.getBytes(StandardCharsets.UTF_8);
				output.writeInt(questionTmp.length);
				output.write(questionTmp);
			}
			if (this.options == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.options.length);
				for (int i = 0; i < this.options.length; i++) {
					this.options[i].serialize(output);
				}
			}
			output.writeInt(this.totalVoterCount);
			if (this.recentVoterUserIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.recentVoterUserIds.length);
				for (int i = 0; i < this.recentVoterUserIds.length; i++) {
					output.writeLong(this.recentVoterUserIds[i]);
				}
			}
			output.writeBoolean(this.isAnonymous);
			if (this.type == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.type.serialize(output);
			}
			output.writeInt(this.openPeriod);
			output.writeInt(this.closeDate);
			output.writeBoolean(this.isClosed);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			Poll poll = (Poll) o;
			if (this.id != poll.id) {
				return false;
			}
			if (this.question != poll.question) {
				return false;
			}
			if (!Arrays.equals(this.options, poll.options)) {
				return false;
			}
			if (this.totalVoterCount != poll.totalVoterCount) {
				return false;
			}
			if (!Arrays.equals(this.recentVoterUserIds, poll.recentVoterUserIds)) {
				return false;
			}
			if (this.isAnonymous != poll.isAnonymous) {
				return false;
			}
			if (!Objects.equals(this.type, poll.type)) {
				return false;
			}
			if (this.openPeriod != poll.openPeriod) {
				return false;
			}
			if (this.closeDate != poll.closeDate) {
				return false;
			}
			if (this.isClosed != poll.isClosed) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.id);
			result = result * 31 + (this.question == null ? 0 : this.question.hashCode());
			result = result * 31 + (Arrays.hashCode(this.options));
			result = result * 31 + (Arrays.hashCode(this.recentVoterUserIds));
			result = result * 31 + (this.type == null ? 0 : this.type.hashCode());
			return result;
		}
	}

	/**
	 * Describes one answer option of a poll.
	**/
	public static final class PollOption extends Object {


		/**
		 * Option text; 1-100 characters.
		**/
		public String text;

		/**
		 * Number of voters for this option, available only for closed or voted polls.
		**/
		public int voterCount;

		/**
		 * The percentage of votes for this option; 0-100.
		**/
		public int votePercentage;

		/**
		 * True, if the option was chosen by the user.
		**/
		public boolean isChosen;

		/**
		 * True, if the option is being chosen by a pending setPollAnswer request.
		**/
		public boolean isBeingChosen;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1473893797;

		/**
		 * Describes one answer option of a poll.
		**/
		public PollOption() {}

		/**
		 * Describes one answer option of a poll.
		 *
		 * @param text Option text; 1-100 characters.
		 * @param voterCount Number of voters for this option, available only for closed or voted polls.
		 * @param votePercentage The percentage of votes for this option; 0-100.
		 * @param isChosen True, if the option was chosen by the user.
		 * @param isBeingChosen True, if the option is being chosen by a pending setPollAnswer request.
		**/
		public PollOption(String text,
				int voterCount,
				int votePercentage,
				boolean isChosen,
				boolean isBeingChosen) {
			this.text = text;
			this.voterCount = voterCount;
			this.votePercentage = votePercentage;
			this.isChosen = isChosen;
			this.isBeingChosen = isBeingChosen;
		}

		/**
		 * Describes one answer option of a poll.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PollOption(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] textTmp = new byte[input.readInt()];
				input.readFully(textTmp);
				this.text = new String(textTmp, StandardCharsets.UTF_8);
			}
			this.voterCount = input.readInt();
			this.votePercentage = input.readInt();
			this.isChosen = input.readBoolean();
			this.isBeingChosen = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PollOption.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PollOption.CONSTRUCTOR);
			if (this.text == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] textTmp = this.text.getBytes(StandardCharsets.UTF_8);
				output.writeInt(textTmp.length);
				output.write(textTmp);
			}
			output.writeInt(this.voterCount);
			output.writeInt(this.votePercentage);
			output.writeBoolean(this.isChosen);
			output.writeBoolean(this.isBeingChosen);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PollOption pollOption = (PollOption) o;
			if (this.text != pollOption.text) {
				return false;
			}
			if (this.voterCount != pollOption.voterCount) {
				return false;
			}
			if (this.votePercentage != pollOption.votePercentage) {
				return false;
			}
			if (this.isChosen != pollOption.isChosen) {
				return false;
			}
			if (this.isBeingChosen != pollOption.isBeingChosen) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.voterCount);
			result = result * 31 + (this.text == null ? 0 : this.text.hashCode());
			return result;
		}
	}

	/**
	 * A regular poll.
	**/
	public static final class PollTypeRegular extends PollType {


		/**
		 * True, if multiple answer options can be chosen simultaneously.
		**/
		public boolean allowMultipleAnswers;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 641265698;

		/**
		 * A regular poll.
		**/
		public PollTypeRegular() {}

		/**
		 * A regular poll.
		 *
		 * @param allowMultipleAnswers True, if multiple answer options can be chosen simultaneously.
		**/
		public PollTypeRegular(boolean allowMultipleAnswers) {
			this.allowMultipleAnswers = allowMultipleAnswers;
		}

		/**
		 * A regular poll.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PollTypeRegular(DataInput input) throws IOException {
			this.allowMultipleAnswers = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PollTypeRegular.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PollTypeRegular.CONSTRUCTOR);
			output.writeBoolean(this.allowMultipleAnswers);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PollTypeRegular pollTypeRegular = (PollTypeRegular) o;
			if (this.allowMultipleAnswers != pollTypeRegular.allowMultipleAnswers) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Boolean.hashCode(this.allowMultipleAnswers);
		}
	}

	/**
	 * A poll in quiz mode, which has exactly one correct answer option and
	 * can be answered only once.
	**/
	public static final class PollTypeQuiz extends PollType {


		/**
		 * 0-based identifier of the correct answer option; -1 for a yet unanswered poll.
		**/
		public int correctOptionId;

		/**
		 * Text that is shown when the user chooses an incorrect answer or taps on the lamp icon; 0-200 characters with at most 2 line feeds; empty for a yet unanswered poll.
		**/
		public FormattedText explanation;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 657013913;

		/**
		 * A poll in quiz mode, which has exactly one correct answer option and can be answered only once.
		**/
		public PollTypeQuiz() {}

		/**
		 * A poll in quiz mode, which has exactly one correct answer option and can be answered only once.
		 *
		 * @param correctOptionId 0-based identifier of the correct answer option; -1 for a yet unanswered poll.
		 * @param explanation Text that is shown when the user chooses an incorrect answer or taps on the lamp icon; 0-200 characters with at most 2 line feeds; empty for a yet unanswered poll.
		**/
		public PollTypeQuiz(int correctOptionId, FormattedText explanation) {
			this.correctOptionId = correctOptionId;
			this.explanation = explanation;
		}

		/**
		 * A poll in quiz mode, which has exactly one correct answer option and can be answered only once.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PollTypeQuiz(DataInput input) throws IOException {
			this.correctOptionId = input.readInt();
			if (input.readBoolean()) {
				if (FormattedText.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.explanation = new FormattedText(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PollTypeQuiz.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PollTypeQuiz.CONSTRUCTOR);
			output.writeInt(this.correctOptionId);
			if (this.explanation == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.explanation.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PollTypeQuiz pollTypeQuiz = (PollTypeQuiz) o;
			if (this.correctOptionId != pollTypeQuiz.correctOptionId) {
				return false;
			}
			if (!Objects.equals(this.explanation, pollTypeQuiz.explanation)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.correctOptionId);
			result = result * 31 + (this.explanation == null ? 0 : this.explanation.hashCode());
			return result;
		}
	}

	/**
	 * Increased limits.
	**/
	public static final class PremiumFeatureIncreasedLimits extends PremiumFeature {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1785455031;

		/**
		 * Increased limits.
		**/
		public PremiumFeatureIncreasedLimits() {}

		/**
		 * Increased limits.
		 *
		**/

		/**
		 * Increased limits.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PremiumFeatureIncreasedLimits(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PremiumFeatureIncreasedLimits.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PremiumFeatureIncreasedLimits.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PremiumFeatureIncreasedLimits.CONSTRUCTOR;
		}
	}

	/**
	 * Increased maximum upload file size.
	**/
	public static final class PremiumFeatureIncreasedUploadFileSize extends PremiumFeature {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1825367155;

		/**
		 * Increased maximum upload file size.
		**/
		public PremiumFeatureIncreasedUploadFileSize() {}

		/**
		 * Increased maximum upload file size.
		 *
		**/

		/**
		 * Increased maximum upload file size.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PremiumFeatureIncreasedUploadFileSize(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PremiumFeatureIncreasedUploadFileSize.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PremiumFeatureIncreasedUploadFileSize.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PremiumFeatureIncreasedUploadFileSize.CONSTRUCTOR;
		}
	}

	/**
	 * Improved download speed.
	**/
	public static final class PremiumFeatureImprovedDownloadSpeed extends PremiumFeature {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -267695554;

		/**
		 * Improved download speed.
		**/
		public PremiumFeatureImprovedDownloadSpeed() {}

		/**
		 * Improved download speed.
		 *
		**/

		/**
		 * Improved download speed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PremiumFeatureImprovedDownloadSpeed(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PremiumFeatureImprovedDownloadSpeed.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PremiumFeatureImprovedDownloadSpeed.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PremiumFeatureImprovedDownloadSpeed.CONSTRUCTOR;
		}
	}

	/**
	 * The ability to convert voice notes to text.
	**/
	public static final class PremiumFeatureVoiceRecognition extends PremiumFeature {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1288216542;

		/**
		 * The ability to convert voice notes to text.
		**/
		public PremiumFeatureVoiceRecognition() {}

		/**
		 * The ability to convert voice notes to text.
		 *
		**/

		/**
		 * The ability to convert voice notes to text.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PremiumFeatureVoiceRecognition(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PremiumFeatureVoiceRecognition.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PremiumFeatureVoiceRecognition.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PremiumFeatureVoiceRecognition.CONSTRUCTOR;
		}
	}

	/**
	 * Disabled ads.
	**/
	public static final class PremiumFeatureDisabledAds extends PremiumFeature {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2008587702;

		/**
		 * Disabled ads.
		**/
		public PremiumFeatureDisabledAds() {}

		/**
		 * Disabled ads.
		 *
		**/

		/**
		 * Disabled ads.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PremiumFeatureDisabledAds(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PremiumFeatureDisabledAds.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PremiumFeatureDisabledAds.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PremiumFeatureDisabledAds.CONSTRUCTOR;
		}
	}

	/**
	 * Allowed to use more reactions.
	**/
	public static final class PremiumFeatureUniqueReactions extends PremiumFeature {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 766750743;

		/**
		 * Allowed to use more reactions.
		**/
		public PremiumFeatureUniqueReactions() {}

		/**
		 * Allowed to use more reactions.
		 *
		**/

		/**
		 * Allowed to use more reactions.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PremiumFeatureUniqueReactions(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PremiumFeatureUniqueReactions.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PremiumFeatureUniqueReactions.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PremiumFeatureUniqueReactions.CONSTRUCTOR;
		}
	}

	/**
	 * Allowed to use premium stickers with unique effects.
	**/
	public static final class PremiumFeatureUniqueStickers extends PremiumFeature {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2101773312;

		/**
		 * Allowed to use premium stickers with unique effects.
		**/
		public PremiumFeatureUniqueStickers() {}

		/**
		 * Allowed to use premium stickers with unique effects.
		 *
		**/

		/**
		 * Allowed to use premium stickers with unique effects.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PremiumFeatureUniqueStickers(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PremiumFeatureUniqueStickers.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PremiumFeatureUniqueStickers.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PremiumFeatureUniqueStickers.CONSTRUCTOR;
		}
	}

	/**
	 * Allowed to use custom emoji stickers in message texts and captions.
	**/
	public static final class PremiumFeatureCustomEmoji extends PremiumFeature {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1332599628;

		/**
		 * Allowed to use custom emoji stickers in message texts and captions.
		**/
		public PremiumFeatureCustomEmoji() {}

		/**
		 * Allowed to use custom emoji stickers in message texts and captions.
		 *
		**/

		/**
		 * Allowed to use custom emoji stickers in message texts and captions.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PremiumFeatureCustomEmoji(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PremiumFeatureCustomEmoji.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PremiumFeatureCustomEmoji.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PremiumFeatureCustomEmoji.CONSTRUCTOR;
		}
	}

	/**
	 * Ability to change position of the main chat list, archive and mute
	 * all new chats from non-contacts, and completely disable notifications
	 * about the user&#039;s contacts joined Telegram.
	**/
	public static final class PremiumFeatureAdvancedChatManagement extends PremiumFeature {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 796347674;

		/**
		 * Ability to change position of the main chat list, archive and mute all new chats from non-contacts, and completely disable notifications about the user&#039;s contacts joined Telegram.
		**/
		public PremiumFeatureAdvancedChatManagement() {}

		/**
		 * Ability to change position of the main chat list, archive and mute all new chats from non-contacts, and completely disable notifications about the user&#039;s contacts joined Telegram.
		 *
		**/

		/**
		 * Ability to change position of the main chat list, archive and mute all new chats from non-contacts, and completely disable notifications about the user&#039;s contacts joined Telegram.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PremiumFeatureAdvancedChatManagement(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PremiumFeatureAdvancedChatManagement.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PremiumFeatureAdvancedChatManagement.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PremiumFeatureAdvancedChatManagement.CONSTRUCTOR;
		}
	}

	/**
	 * A badge in the user&#039;s profile.
	**/
	public static final class PremiumFeatureProfileBadge extends PremiumFeature {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 233648322;

		/**
		 * A badge in the user&#039;s profile.
		**/
		public PremiumFeatureProfileBadge() {}

		/**
		 * A badge in the user&#039;s profile.
		 *
		**/

		/**
		 * A badge in the user&#039;s profile.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PremiumFeatureProfileBadge(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PremiumFeatureProfileBadge.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PremiumFeatureProfileBadge.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PremiumFeatureProfileBadge.CONSTRUCTOR;
		}
	}

	/**
	 * A emoji status shown along with the user&#039;s name.
	**/
	public static final class PremiumFeatureEmojiStatus extends PremiumFeature {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -36516639;

		/**
		 * A emoji status shown along with the user&#039;s name.
		**/
		public PremiumFeatureEmojiStatus() {}

		/**
		 * A emoji status shown along with the user&#039;s name.
		 *
		**/

		/**
		 * A emoji status shown along with the user&#039;s name.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PremiumFeatureEmojiStatus(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PremiumFeatureEmojiStatus.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PremiumFeatureEmojiStatus.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PremiumFeatureEmojiStatus.CONSTRUCTOR;
		}
	}

	/**
	 * Profile photo animation on message and chat screens.
	**/
	public static final class PremiumFeatureAnimatedProfilePhoto extends PremiumFeature {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -100741914;

		/**
		 * Profile photo animation on message and chat screens.
		**/
		public PremiumFeatureAnimatedProfilePhoto() {}

		/**
		 * Profile photo animation on message and chat screens.
		 *
		**/

		/**
		 * Profile photo animation on message and chat screens.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PremiumFeatureAnimatedProfilePhoto(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PremiumFeatureAnimatedProfilePhoto.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PremiumFeatureAnimatedProfilePhoto.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PremiumFeatureAnimatedProfilePhoto.CONSTRUCTOR;
		}
	}

	/**
	 * The ability to set a custom emoji as a forum topic icon.
	**/
	public static final class PremiumFeatureForumTopicIcon extends PremiumFeature {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -823172286;

		/**
		 * The ability to set a custom emoji as a forum topic icon.
		**/
		public PremiumFeatureForumTopicIcon() {}

		/**
		 * The ability to set a custom emoji as a forum topic icon.
		 *
		**/

		/**
		 * The ability to set a custom emoji as a forum topic icon.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PremiumFeatureForumTopicIcon(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PremiumFeatureForumTopicIcon.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PremiumFeatureForumTopicIcon.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PremiumFeatureForumTopicIcon.CONSTRUCTOR;
		}
	}

	/**
	 * Allowed to set a premium application icons.
	**/
	public static final class PremiumFeatureAppIcons extends PremiumFeature {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1585050761;

		/**
		 * Allowed to set a premium application icons.
		**/
		public PremiumFeatureAppIcons() {}

		/**
		 * Allowed to set a premium application icons.
		 *
		**/

		/**
		 * Allowed to set a premium application icons.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PremiumFeatureAppIcons(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PremiumFeatureAppIcons.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PremiumFeatureAppIcons.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PremiumFeatureAppIcons.CONSTRUCTOR;
		}
	}

	/**
	 * Allowed to translate chat messages real-time.
	**/
	public static final class PremiumFeatureRealTimeChatTranslation extends PremiumFeature {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1143471488;

		/**
		 * Allowed to translate chat messages real-time.
		**/
		public PremiumFeatureRealTimeChatTranslation() {}

		/**
		 * Allowed to translate chat messages real-time.
		 *
		**/

		/**
		 * Allowed to translate chat messages real-time.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PremiumFeatureRealTimeChatTranslation(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PremiumFeatureRealTimeChatTranslation.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PremiumFeatureRealTimeChatTranslation.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PremiumFeatureRealTimeChatTranslation.CONSTRUCTOR;
		}
	}

	/**
	 * Describes a promotion animation for a Premium feature.
	**/
	public static final class PremiumFeaturePromotionAnimation extends Object {


		/**
		 * Premium feature.
		**/
		public PremiumFeature feature;

		/**
		 * Promotion animation for the feature.
		**/
		public Animation animation;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1986155748;

		/**
		 * Describes a promotion animation for a Premium feature.
		**/
		public PremiumFeaturePromotionAnimation() {}

		/**
		 * Describes a promotion animation for a Premium feature.
		 *
		 * @param feature Premium feature.
		 * @param animation Promotion animation for the feature.
		**/
		public PremiumFeaturePromotionAnimation(PremiumFeature feature, Animation animation) {
			this.feature = feature;
			this.animation = animation;
		}

		/**
		 * Describes a promotion animation for a Premium feature.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PremiumFeaturePromotionAnimation(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case PremiumFeatureIncreasedLimits.CONSTRUCTOR: this.feature = new PremiumFeatureIncreasedLimits(input); break;
					case PremiumFeatureIncreasedUploadFileSize.CONSTRUCTOR: this.feature = new PremiumFeatureIncreasedUploadFileSize(input); break;
					case PremiumFeatureImprovedDownloadSpeed.CONSTRUCTOR: this.feature = new PremiumFeatureImprovedDownloadSpeed(input); break;
					case PremiumFeatureVoiceRecognition.CONSTRUCTOR: this.feature = new PremiumFeatureVoiceRecognition(input); break;
					case PremiumFeatureDisabledAds.CONSTRUCTOR: this.feature = new PremiumFeatureDisabledAds(input); break;
					case PremiumFeatureUniqueReactions.CONSTRUCTOR: this.feature = new PremiumFeatureUniqueReactions(input); break;
					case PremiumFeatureUniqueStickers.CONSTRUCTOR: this.feature = new PremiumFeatureUniqueStickers(input); break;
					case PremiumFeatureCustomEmoji.CONSTRUCTOR: this.feature = new PremiumFeatureCustomEmoji(input); break;
					case PremiumFeatureAdvancedChatManagement.CONSTRUCTOR: this.feature = new PremiumFeatureAdvancedChatManagement(input); break;
					case PremiumFeatureProfileBadge.CONSTRUCTOR: this.feature = new PremiumFeatureProfileBadge(input); break;
					case PremiumFeatureEmojiStatus.CONSTRUCTOR: this.feature = new PremiumFeatureEmojiStatus(input); break;
					case PremiumFeatureAnimatedProfilePhoto.CONSTRUCTOR: this.feature = new PremiumFeatureAnimatedProfilePhoto(input); break;
					case PremiumFeatureForumTopicIcon.CONSTRUCTOR: this.feature = new PremiumFeatureForumTopicIcon(input); break;
					case PremiumFeatureAppIcons.CONSTRUCTOR: this.feature = new PremiumFeatureAppIcons(input); break;
					case PremiumFeatureRealTimeChatTranslation.CONSTRUCTOR: this.feature = new PremiumFeatureRealTimeChatTranslation(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				if (Animation.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.animation = new Animation(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PremiumFeaturePromotionAnimation.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PremiumFeaturePromotionAnimation.CONSTRUCTOR);
			if (this.feature == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.feature.serialize(output);
			}
			if (this.animation == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.animation.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PremiumFeaturePromotionAnimation premiumFeaturePromotionAnimation = (PremiumFeaturePromotionAnimation) o;
			if (!Objects.equals(this.feature, premiumFeaturePromotionAnimation.feature)) {
				return false;
			}
			if (!Objects.equals(this.animation, premiumFeaturePromotionAnimation.animation)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.feature == null ? 0 : this.feature.hashCode();
			result = result * 31 + (this.animation == null ? 0 : this.animation.hashCode());
			return result;
		}
	}

	/**
	 * Contains information about features, available to Premium users.
	**/
	public static final class PremiumFeatures extends Object {


		/**
		 * The list of available features.
		**/
		public PremiumFeature[] features;

		/**
		 * The list of limits, increased for Premium users.
		**/
		public PremiumLimit[] limits;

		/**
		 * An internal link to be opened to pay for Telegram Premium if store payment isn&#039;t possible; may be null if direct payment isn&#039;t available.
		**/
		public InternalLinkType paymentLink;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1875162172;

		/**
		 * Contains information about features, available to Premium users.
		**/
		public PremiumFeatures() {}

		/**
		 * Contains information about features, available to Premium users.
		 *
		 * @param features The list of available features.
		 * @param limits The list of limits, increased for Premium users.
		 * @param paymentLink An internal link to be opened to pay for Telegram Premium if store payment isn&#039;t possible; may be null if direct payment isn&#039;t available.
		**/
		public PremiumFeatures(PremiumFeature[] features,
				PremiumLimit[] limits,
				InternalLinkType paymentLink) {
			this.features = features;
			this.limits = limits;
			this.paymentLink = paymentLink;
		}

		/**
		 * Contains information about features, available to Premium users.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PremiumFeatures(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.features = new PremiumFeature[input.readInt()];
				for (int i = 0; i < this.features.length; i++) {
					switch(input.readInt()) {
						case PremiumFeatureIncreasedLimits.CONSTRUCTOR: this.features[i] = new PremiumFeatureIncreasedLimits(input); break;
						case PremiumFeatureIncreasedUploadFileSize.CONSTRUCTOR: this.features[i] = new PremiumFeatureIncreasedUploadFileSize(input); break;
						case PremiumFeatureImprovedDownloadSpeed.CONSTRUCTOR: this.features[i] = new PremiumFeatureImprovedDownloadSpeed(input); break;
						case PremiumFeatureVoiceRecognition.CONSTRUCTOR: this.features[i] = new PremiumFeatureVoiceRecognition(input); break;
						case PremiumFeatureDisabledAds.CONSTRUCTOR: this.features[i] = new PremiumFeatureDisabledAds(input); break;
						case PremiumFeatureUniqueReactions.CONSTRUCTOR: this.features[i] = new PremiumFeatureUniqueReactions(input); break;
						case PremiumFeatureUniqueStickers.CONSTRUCTOR: this.features[i] = new PremiumFeatureUniqueStickers(input); break;
						case PremiumFeatureCustomEmoji.CONSTRUCTOR: this.features[i] = new PremiumFeatureCustomEmoji(input); break;
						case PremiumFeatureAdvancedChatManagement.CONSTRUCTOR: this.features[i] = new PremiumFeatureAdvancedChatManagement(input); break;
						case PremiumFeatureProfileBadge.CONSTRUCTOR: this.features[i] = new PremiumFeatureProfileBadge(input); break;
						case PremiumFeatureEmojiStatus.CONSTRUCTOR: this.features[i] = new PremiumFeatureEmojiStatus(input); break;
						case PremiumFeatureAnimatedProfilePhoto.CONSTRUCTOR: this.features[i] = new PremiumFeatureAnimatedProfilePhoto(input); break;
						case PremiumFeatureForumTopicIcon.CONSTRUCTOR: this.features[i] = new PremiumFeatureForumTopicIcon(input); break;
						case PremiumFeatureAppIcons.CONSTRUCTOR: this.features[i] = new PremiumFeatureAppIcons(input); break;
						case PremiumFeatureRealTimeChatTranslation.CONSTRUCTOR: this.features[i] = new PremiumFeatureRealTimeChatTranslation(input); break;
						default: {
							throw new UnsupportedOperationException();
						}
					}
				}
			}
			if (input.readBoolean()) {
				this.limits = new PremiumLimit[input.readInt()];
				for (int i = 0; i < this.limits.length; i++) {
					if (PremiumLimit.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.limits[i] = new PremiumLimit(input);
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InternalLinkTypeActiveSessions.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeActiveSessions(input); break;
					case InternalLinkTypeAttachmentMenuBot.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeAttachmentMenuBot(input); break;
					case InternalLinkTypeAuthenticationCode.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeAuthenticationCode(input); break;
					case InternalLinkTypeBackground.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeBackground(input); break;
					case InternalLinkTypeBotAddToChannel.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeBotAddToChannel(input); break;
					case InternalLinkTypeBotStart.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeBotStart(input); break;
					case InternalLinkTypeBotStartInGroup.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeBotStartInGroup(input); break;
					case InternalLinkTypeChangePhoneNumber.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeChangePhoneNumber(input); break;
					case InternalLinkTypeChatFolderInvite.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeChatFolderInvite(input); break;
					case InternalLinkTypeChatFolderSettings.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeChatFolderSettings(input); break;
					case InternalLinkTypeChatInvite.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeChatInvite(input); break;
					case InternalLinkTypeDefaultMessageAutoDeleteTimerSettings.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeDefaultMessageAutoDeleteTimerSettings(input); break;
					case InternalLinkTypeEditProfileSettings.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeEditProfileSettings(input); break;
					case InternalLinkTypeGame.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeGame(input); break;
					case InternalLinkTypeInstantView.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeInstantView(input); break;
					case InternalLinkTypeInvoice.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeInvoice(input); break;
					case InternalLinkTypeLanguagePack.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeLanguagePack(input); break;
					case InternalLinkTypeLanguageSettings.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeLanguageSettings(input); break;
					case InternalLinkTypeMessage.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeMessage(input); break;
					case InternalLinkTypeMessageDraft.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeMessageDraft(input); break;
					case InternalLinkTypePassportDataRequest.CONSTRUCTOR: this.paymentLink = new InternalLinkTypePassportDataRequest(input); break;
					case InternalLinkTypePhoneNumberConfirmation.CONSTRUCTOR: this.paymentLink = new InternalLinkTypePhoneNumberConfirmation(input); break;
					case InternalLinkTypePremiumFeatures.CONSTRUCTOR: this.paymentLink = new InternalLinkTypePremiumFeatures(input); break;
					case InternalLinkTypePrivacyAndSecuritySettings.CONSTRUCTOR: this.paymentLink = new InternalLinkTypePrivacyAndSecuritySettings(input); break;
					case InternalLinkTypeProxy.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeProxy(input); break;
					case InternalLinkTypePublicChat.CONSTRUCTOR: this.paymentLink = new InternalLinkTypePublicChat(input); break;
					case InternalLinkTypeQrCodeAuthentication.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeQrCodeAuthentication(input); break;
					case InternalLinkTypeRestorePurchases.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeRestorePurchases(input); break;
					case InternalLinkTypeSettings.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeSettings(input); break;
					case InternalLinkTypeStickerSet.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeStickerSet(input); break;
					case InternalLinkTypeTheme.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeTheme(input); break;
					case InternalLinkTypeThemeSettings.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeThemeSettings(input); break;
					case InternalLinkTypeUnknownDeepLink.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeUnknownDeepLink(input); break;
					case InternalLinkTypeUnsupportedProxy.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeUnsupportedProxy(input); break;
					case InternalLinkTypeUserPhoneNumber.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeUserPhoneNumber(input); break;
					case InternalLinkTypeUserToken.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeUserToken(input); break;
					case InternalLinkTypeVideoChat.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeVideoChat(input); break;
					case InternalLinkTypeWebApp.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeWebApp(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PremiumFeatures.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PremiumFeatures.CONSTRUCTOR);
			if (this.features == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.features.length);
				for (int i = 0; i < this.features.length; i++) {
					this.features[i].serialize(output);
				}
			}
			if (this.limits == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.limits.length);
				for (int i = 0; i < this.limits.length; i++) {
					this.limits[i].serialize(output);
				}
			}
			if (this.paymentLink == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.paymentLink.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PremiumFeatures premiumFeatures = (PremiumFeatures) o;
			if (!Arrays.equals(this.features, premiumFeatures.features)) {
				return false;
			}
			if (!Arrays.equals(this.limits, premiumFeatures.limits)) {
				return false;
			}
			if (!Objects.equals(this.paymentLink, premiumFeatures.paymentLink)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Arrays.hashCode(this.features);
			result = result * 31 + (Arrays.hashCode(this.limits));
			result = result * 31 + (this.paymentLink == null ? 0 : this.paymentLink.hashCode());
			return result;
		}
	}

	/**
	 * Contains information about a limit, increased for Premium users.
	**/
	public static final class PremiumLimit extends Object {


		/**
		 * The type of the limit.
		**/
		public PremiumLimitType type;

		/**
		 * Default value of the limit.
		**/
		public int defaultValue;

		/**
		 * Value of the limit for Premium users.
		**/
		public int premiumValue;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2127786726;

		/**
		 * Contains information about a limit, increased for Premium users.
		**/
		public PremiumLimit() {}

		/**
		 * Contains information about a limit, increased for Premium users.
		 *
		 * @param type The type of the limit.
		 * @param defaultValue Default value of the limit.
		 * @param premiumValue Value of the limit for Premium users.
		**/
		public PremiumLimit(PremiumLimitType type, int defaultValue, int premiumValue) {
			this.type = type;
			this.defaultValue = defaultValue;
			this.premiumValue = premiumValue;
		}

		/**
		 * Contains information about a limit, increased for Premium users.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PremiumLimit(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case PremiumLimitTypeSupergroupCount.CONSTRUCTOR: this.type = new PremiumLimitTypeSupergroupCount(input); break;
					case PremiumLimitTypePinnedChatCount.CONSTRUCTOR: this.type = new PremiumLimitTypePinnedChatCount(input); break;
					case PremiumLimitTypeCreatedPublicChatCount.CONSTRUCTOR: this.type = new PremiumLimitTypeCreatedPublicChatCount(input); break;
					case PremiumLimitTypeSavedAnimationCount.CONSTRUCTOR: this.type = new PremiumLimitTypeSavedAnimationCount(input); break;
					case PremiumLimitTypeFavoriteStickerCount.CONSTRUCTOR: this.type = new PremiumLimitTypeFavoriteStickerCount(input); break;
					case PremiumLimitTypeChatFolderCount.CONSTRUCTOR: this.type = new PremiumLimitTypeChatFolderCount(input); break;
					case PremiumLimitTypeChatFolderChosenChatCount.CONSTRUCTOR: this.type = new PremiumLimitTypeChatFolderChosenChatCount(input); break;
					case PremiumLimitTypePinnedArchivedChatCount.CONSTRUCTOR: this.type = new PremiumLimitTypePinnedArchivedChatCount(input); break;
					case PremiumLimitTypeCaptionLength.CONSTRUCTOR: this.type = new PremiumLimitTypeCaptionLength(input); break;
					case PremiumLimitTypeBioLength.CONSTRUCTOR: this.type = new PremiumLimitTypeBioLength(input); break;
					case PremiumLimitTypeChatFolderInviteLinkCount.CONSTRUCTOR: this.type = new PremiumLimitTypeChatFolderInviteLinkCount(input); break;
					case PremiumLimitTypeShareableChatFolderCount.CONSTRUCTOR: this.type = new PremiumLimitTypeShareableChatFolderCount(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.defaultValue = input.readInt();
			this.premiumValue = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PremiumLimit.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PremiumLimit.CONSTRUCTOR);
			if (this.type == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.type.serialize(output);
			}
			output.writeInt(this.defaultValue);
			output.writeInt(this.premiumValue);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PremiumLimit premiumLimit = (PremiumLimit) o;
			if (!Objects.equals(this.type, premiumLimit.type)) {
				return false;
			}
			if (this.defaultValue != premiumLimit.defaultValue) {
				return false;
			}
			if (this.premiumValue != premiumLimit.premiumValue) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.defaultValue);
			result = result * 31 + (this.type == null ? 0 : this.type.hashCode());
			return result;
		}
	}

	/**
	 * The maximum number of joined supergroups and channels.
	**/
	public static final class PremiumLimitTypeSupergroupCount extends PremiumLimitType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -247467131;

		/**
		 * The maximum number of joined supergroups and channels.
		**/
		public PremiumLimitTypeSupergroupCount() {}

		/**
		 * The maximum number of joined supergroups and channels.
		 *
		**/

		/**
		 * The maximum number of joined supergroups and channels.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PremiumLimitTypeSupergroupCount(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PremiumLimitTypeSupergroupCount.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PremiumLimitTypeSupergroupCount.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PremiumLimitTypeSupergroupCount.CONSTRUCTOR;
		}
	}

	/**
	 * The maximum number of pinned chats in the main chat list.
	**/
	public static final class PremiumLimitTypePinnedChatCount extends PremiumLimitType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -998947871;

		/**
		 * The maximum number of pinned chats in the main chat list.
		**/
		public PremiumLimitTypePinnedChatCount() {}

		/**
		 * The maximum number of pinned chats in the main chat list.
		 *
		**/

		/**
		 * The maximum number of pinned chats in the main chat list.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PremiumLimitTypePinnedChatCount(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PremiumLimitTypePinnedChatCount.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PremiumLimitTypePinnedChatCount.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PremiumLimitTypePinnedChatCount.CONSTRUCTOR;
		}
	}

	/**
	 * The maximum number of created public chats.
	**/
	public static final class PremiumLimitTypeCreatedPublicChatCount extends PremiumLimitType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 446086841;

		/**
		 * The maximum number of created public chats.
		**/
		public PremiumLimitTypeCreatedPublicChatCount() {}

		/**
		 * The maximum number of created public chats.
		 *
		**/

		/**
		 * The maximum number of created public chats.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PremiumLimitTypeCreatedPublicChatCount(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PremiumLimitTypeCreatedPublicChatCount.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PremiumLimitTypeCreatedPublicChatCount.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PremiumLimitTypeCreatedPublicChatCount.CONSTRUCTOR;
		}
	}

	/**
	 * The maximum number of saved animations.
	**/
	public static final class PremiumLimitTypeSavedAnimationCount extends PremiumLimitType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -19759735;

		/**
		 * The maximum number of saved animations.
		**/
		public PremiumLimitTypeSavedAnimationCount() {}

		/**
		 * The maximum number of saved animations.
		 *
		**/

		/**
		 * The maximum number of saved animations.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PremiumLimitTypeSavedAnimationCount(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PremiumLimitTypeSavedAnimationCount.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PremiumLimitTypeSavedAnimationCount.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PremiumLimitTypeSavedAnimationCount.CONSTRUCTOR;
		}
	}

	/**
	 * The maximum number of favorite stickers.
	**/
	public static final class PremiumLimitTypeFavoriteStickerCount extends PremiumLimitType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 639754787;

		/**
		 * The maximum number of favorite stickers.
		**/
		public PremiumLimitTypeFavoriteStickerCount() {}

		/**
		 * The maximum number of favorite stickers.
		 *
		**/

		/**
		 * The maximum number of favorite stickers.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PremiumLimitTypeFavoriteStickerCount(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PremiumLimitTypeFavoriteStickerCount.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PremiumLimitTypeFavoriteStickerCount.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PremiumLimitTypeFavoriteStickerCount.CONSTRUCTOR;
		}
	}

	/**
	 * The maximum number of chat folders.
	**/
	public static final class PremiumLimitTypeChatFolderCount extends PremiumLimitType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 377489774;

		/**
		 * The maximum number of chat folders.
		**/
		public PremiumLimitTypeChatFolderCount() {}

		/**
		 * The maximum number of chat folders.
		 *
		**/

		/**
		 * The maximum number of chat folders.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PremiumLimitTypeChatFolderCount(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PremiumLimitTypeChatFolderCount.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PremiumLimitTypeChatFolderCount.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PremiumLimitTypeChatFolderCount.CONSTRUCTOR;
		}
	}

	/**
	 * The maximum number of pinned and always included, or always excluded
	 * chats in a chat folder.
	**/
	public static final class PremiumLimitTypeChatFolderChosenChatCount extends PremiumLimitType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1691435861;

		/**
		 * The maximum number of pinned and always included, or always excluded chats in a chat folder.
		**/
		public PremiumLimitTypeChatFolderChosenChatCount() {}

		/**
		 * The maximum number of pinned and always included, or always excluded chats in a chat folder.
		 *
		**/

		/**
		 * The maximum number of pinned and always included, or always excluded chats in a chat folder.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PremiumLimitTypeChatFolderChosenChatCount(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PremiumLimitTypeChatFolderChosenChatCount.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PremiumLimitTypeChatFolderChosenChatCount.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PremiumLimitTypeChatFolderChosenChatCount.CONSTRUCTOR;
		}
	}

	/**
	 * The maximum number of pinned chats in the archive chat list.
	**/
	public static final class PremiumLimitTypePinnedArchivedChatCount extends PremiumLimitType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1485515276;

		/**
		 * The maximum number of pinned chats in the archive chat list.
		**/
		public PremiumLimitTypePinnedArchivedChatCount() {}

		/**
		 * The maximum number of pinned chats in the archive chat list.
		 *
		**/

		/**
		 * The maximum number of pinned chats in the archive chat list.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PremiumLimitTypePinnedArchivedChatCount(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PremiumLimitTypePinnedArchivedChatCount.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PremiumLimitTypePinnedArchivedChatCount.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PremiumLimitTypePinnedArchivedChatCount.CONSTRUCTOR;
		}
	}

	/**
	 * The maximum length of sent media caption.
	**/
	public static final class PremiumLimitTypeCaptionLength extends PremiumLimitType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 293984314;

		/**
		 * The maximum length of sent media caption.
		**/
		public PremiumLimitTypeCaptionLength() {}

		/**
		 * The maximum length of sent media caption.
		 *
		**/

		/**
		 * The maximum length of sent media caption.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PremiumLimitTypeCaptionLength(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PremiumLimitTypeCaptionLength.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PremiumLimitTypeCaptionLength.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PremiumLimitTypeCaptionLength.CONSTRUCTOR;
		}
	}

	/**
	 * The maximum length of the user&#039;s bio.
	**/
	public static final class PremiumLimitTypeBioLength extends PremiumLimitType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1146976765;

		/**
		 * The maximum length of the user&#039;s bio.
		**/
		public PremiumLimitTypeBioLength() {}

		/**
		 * The maximum length of the user&#039;s bio.
		 *
		**/

		/**
		 * The maximum length of the user&#039;s bio.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PremiumLimitTypeBioLength(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PremiumLimitTypeBioLength.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PremiumLimitTypeBioLength.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PremiumLimitTypeBioLength.CONSTRUCTOR;
		}
	}

	/**
	 * The maximum number of invite links for a chat folder.
	**/
	public static final class PremiumLimitTypeChatFolderInviteLinkCount extends PremiumLimitType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -128702950;

		/**
		 * The maximum number of invite links for a chat folder.
		**/
		public PremiumLimitTypeChatFolderInviteLinkCount() {}

		/**
		 * The maximum number of invite links for a chat folder.
		 *
		**/

		/**
		 * The maximum number of invite links for a chat folder.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PremiumLimitTypeChatFolderInviteLinkCount(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PremiumLimitTypeChatFolderInviteLinkCount.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PremiumLimitTypeChatFolderInviteLinkCount.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PremiumLimitTypeChatFolderInviteLinkCount.CONSTRUCTOR;
		}
	}

	/**
	 * The maximum number of added shareable chat folders.
	**/
	public static final class PremiumLimitTypeShareableChatFolderCount extends PremiumLimitType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1612625095;

		/**
		 * The maximum number of added shareable chat folders.
		**/
		public PremiumLimitTypeShareableChatFolderCount() {}

		/**
		 * The maximum number of added shareable chat folders.
		 *
		**/

		/**
		 * The maximum number of added shareable chat folders.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PremiumLimitTypeShareableChatFolderCount(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PremiumLimitTypeShareableChatFolderCount.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PremiumLimitTypeShareableChatFolderCount.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PremiumLimitTypeShareableChatFolderCount.CONSTRUCTOR;
		}
	}

	/**
	 * Describes an option for buying Telegram Premium to a user.
	**/
	public static final class PremiumPaymentOption extends Object {


		/**
		 * ISO 4217 currency code for Telegram Premium subscription payment.
		**/
		public String currency;

		/**
		 * The amount to pay, in the smallest units of the currency.
		**/
		public long amount;

		/**
		 * The discount associated with this option, as a percentage.
		**/
		public int discountPercentage;

		/**
		 * Number of month the Telegram Premium subscription will be active.
		**/
		public int monthCount;

		/**
		 * Identifier of the store product associated with the option.
		**/
		public String storeProductId;

		/**
		 * An internal link to be opened for buying Telegram Premium to the user if store payment isn&#039;t possible; may be null if direct payment isn&#039;t available.
		**/
		public InternalLinkType paymentLink;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1945346126;

		/**
		 * Describes an option for buying Telegram Premium to a user.
		**/
		public PremiumPaymentOption() {}

		/**
		 * Describes an option for buying Telegram Premium to a user.
		 *
		 * @param currency ISO 4217 currency code for Telegram Premium subscription payment.
		 * @param amount The amount to pay, in the smallest units of the currency.
		 * @param discountPercentage The discount associated with this option, as a percentage.
		 * @param monthCount Number of month the Telegram Premium subscription will be active.
		 * @param storeProductId Identifier of the store product associated with the option.
		 * @param paymentLink An internal link to be opened for buying Telegram Premium to the user if store payment isn&#039;t possible; may be null if direct payment isn&#039;t available.
		**/
		public PremiumPaymentOption(String currency,
				long amount,
				int discountPercentage,
				int monthCount,
				String storeProductId,
				InternalLinkType paymentLink) {
			this.currency = currency;
			this.amount = amount;
			this.discountPercentage = discountPercentage;
			this.monthCount = monthCount;
			this.storeProductId = storeProductId;
			this.paymentLink = paymentLink;
		}

		/**
		 * Describes an option for buying Telegram Premium to a user.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PremiumPaymentOption(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] currencyTmp = new byte[input.readInt()];
				input.readFully(currencyTmp);
				this.currency = new String(currencyTmp, StandardCharsets.UTF_8);
			}
			this.amount = input.readLong();
			this.discountPercentage = input.readInt();
			this.monthCount = input.readInt();
			if (input.readBoolean()) {
				byte[] storeProductIdTmp = new byte[input.readInt()];
				input.readFully(storeProductIdTmp);
				this.storeProductId = new String(storeProductIdTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InternalLinkTypeActiveSessions.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeActiveSessions(input); break;
					case InternalLinkTypeAttachmentMenuBot.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeAttachmentMenuBot(input); break;
					case InternalLinkTypeAuthenticationCode.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeAuthenticationCode(input); break;
					case InternalLinkTypeBackground.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeBackground(input); break;
					case InternalLinkTypeBotAddToChannel.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeBotAddToChannel(input); break;
					case InternalLinkTypeBotStart.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeBotStart(input); break;
					case InternalLinkTypeBotStartInGroup.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeBotStartInGroup(input); break;
					case InternalLinkTypeChangePhoneNumber.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeChangePhoneNumber(input); break;
					case InternalLinkTypeChatFolderInvite.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeChatFolderInvite(input); break;
					case InternalLinkTypeChatFolderSettings.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeChatFolderSettings(input); break;
					case InternalLinkTypeChatInvite.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeChatInvite(input); break;
					case InternalLinkTypeDefaultMessageAutoDeleteTimerSettings.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeDefaultMessageAutoDeleteTimerSettings(input); break;
					case InternalLinkTypeEditProfileSettings.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeEditProfileSettings(input); break;
					case InternalLinkTypeGame.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeGame(input); break;
					case InternalLinkTypeInstantView.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeInstantView(input); break;
					case InternalLinkTypeInvoice.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeInvoice(input); break;
					case InternalLinkTypeLanguagePack.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeLanguagePack(input); break;
					case InternalLinkTypeLanguageSettings.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeLanguageSettings(input); break;
					case InternalLinkTypeMessage.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeMessage(input); break;
					case InternalLinkTypeMessageDraft.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeMessageDraft(input); break;
					case InternalLinkTypePassportDataRequest.CONSTRUCTOR: this.paymentLink = new InternalLinkTypePassportDataRequest(input); break;
					case InternalLinkTypePhoneNumberConfirmation.CONSTRUCTOR: this.paymentLink = new InternalLinkTypePhoneNumberConfirmation(input); break;
					case InternalLinkTypePremiumFeatures.CONSTRUCTOR: this.paymentLink = new InternalLinkTypePremiumFeatures(input); break;
					case InternalLinkTypePrivacyAndSecuritySettings.CONSTRUCTOR: this.paymentLink = new InternalLinkTypePrivacyAndSecuritySettings(input); break;
					case InternalLinkTypeProxy.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeProxy(input); break;
					case InternalLinkTypePublicChat.CONSTRUCTOR: this.paymentLink = new InternalLinkTypePublicChat(input); break;
					case InternalLinkTypeQrCodeAuthentication.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeQrCodeAuthentication(input); break;
					case InternalLinkTypeRestorePurchases.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeRestorePurchases(input); break;
					case InternalLinkTypeSettings.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeSettings(input); break;
					case InternalLinkTypeStickerSet.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeStickerSet(input); break;
					case InternalLinkTypeTheme.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeTheme(input); break;
					case InternalLinkTypeThemeSettings.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeThemeSettings(input); break;
					case InternalLinkTypeUnknownDeepLink.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeUnknownDeepLink(input); break;
					case InternalLinkTypeUnsupportedProxy.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeUnsupportedProxy(input); break;
					case InternalLinkTypeUserPhoneNumber.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeUserPhoneNumber(input); break;
					case InternalLinkTypeUserToken.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeUserToken(input); break;
					case InternalLinkTypeVideoChat.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeVideoChat(input); break;
					case InternalLinkTypeWebApp.CONSTRUCTOR: this.paymentLink = new InternalLinkTypeWebApp(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PremiumPaymentOption.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PremiumPaymentOption.CONSTRUCTOR);
			if (this.currency == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] currencyTmp = this.currency.getBytes(StandardCharsets.UTF_8);
				output.writeInt(currencyTmp.length);
				output.write(currencyTmp);
			}
			output.writeLong(this.amount);
			output.writeInt(this.discountPercentage);
			output.writeInt(this.monthCount);
			if (this.storeProductId == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] storeProductIdTmp = this.storeProductId.getBytes(StandardCharsets.UTF_8);
				output.writeInt(storeProductIdTmp.length);
				output.write(storeProductIdTmp);
			}
			if (this.paymentLink == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.paymentLink.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PremiumPaymentOption premiumPaymentOption = (PremiumPaymentOption) o;
			if (this.currency != premiumPaymentOption.currency) {
				return false;
			}
			if (this.amount != premiumPaymentOption.amount) {
				return false;
			}
			if (this.discountPercentage != premiumPaymentOption.discountPercentage) {
				return false;
			}
			if (this.monthCount != premiumPaymentOption.monthCount) {
				return false;
			}
			if (this.storeProductId != premiumPaymentOption.storeProductId) {
				return false;
			}
			if (!Objects.equals(this.paymentLink, premiumPaymentOption.paymentLink)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.amount);
			result = result * 31 + (this.currency == null ? 0 : this.currency.hashCode());
			result = result * 31 + (this.storeProductId == null ? 0 : this.storeProductId.hashCode());
			result = result * 31 + (this.paymentLink == null ? 0 : this.paymentLink.hashCode());
			return result;
		}
	}

	/**
	 * A limit was exceeded.
	**/
	public static final class PremiumSourceLimitExceeded extends PremiumSource {


		/**
		 * Type of the exceeded limit.
		**/
		public PremiumLimitType limitType;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2052159742;

		/**
		 * A limit was exceeded.
		**/
		public PremiumSourceLimitExceeded() {}

		/**
		 * A limit was exceeded.
		 *
		 * @param limitType Type of the exceeded limit.
		**/
		public PremiumSourceLimitExceeded(PremiumLimitType limitType) {
			this.limitType = limitType;
		}

		/**
		 * A limit was exceeded.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PremiumSourceLimitExceeded(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case PremiumLimitTypeSupergroupCount.CONSTRUCTOR: this.limitType = new PremiumLimitTypeSupergroupCount(input); break;
					case PremiumLimitTypePinnedChatCount.CONSTRUCTOR: this.limitType = new PremiumLimitTypePinnedChatCount(input); break;
					case PremiumLimitTypeCreatedPublicChatCount.CONSTRUCTOR: this.limitType = new PremiumLimitTypeCreatedPublicChatCount(input); break;
					case PremiumLimitTypeSavedAnimationCount.CONSTRUCTOR: this.limitType = new PremiumLimitTypeSavedAnimationCount(input); break;
					case PremiumLimitTypeFavoriteStickerCount.CONSTRUCTOR: this.limitType = new PremiumLimitTypeFavoriteStickerCount(input); break;
					case PremiumLimitTypeChatFolderCount.CONSTRUCTOR: this.limitType = new PremiumLimitTypeChatFolderCount(input); break;
					case PremiumLimitTypeChatFolderChosenChatCount.CONSTRUCTOR: this.limitType = new PremiumLimitTypeChatFolderChosenChatCount(input); break;
					case PremiumLimitTypePinnedArchivedChatCount.CONSTRUCTOR: this.limitType = new PremiumLimitTypePinnedArchivedChatCount(input); break;
					case PremiumLimitTypeCaptionLength.CONSTRUCTOR: this.limitType = new PremiumLimitTypeCaptionLength(input); break;
					case PremiumLimitTypeBioLength.CONSTRUCTOR: this.limitType = new PremiumLimitTypeBioLength(input); break;
					case PremiumLimitTypeChatFolderInviteLinkCount.CONSTRUCTOR: this.limitType = new PremiumLimitTypeChatFolderInviteLinkCount(input); break;
					case PremiumLimitTypeShareableChatFolderCount.CONSTRUCTOR: this.limitType = new PremiumLimitTypeShareableChatFolderCount(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PremiumSourceLimitExceeded.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PremiumSourceLimitExceeded.CONSTRUCTOR);
			if (this.limitType == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.limitType.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PremiumSourceLimitExceeded premiumSourceLimitExceeded = (PremiumSourceLimitExceeded) o;
			if (!Objects.equals(this.limitType, premiumSourceLimitExceeded.limitType)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.limitType == null ? 0 : this.limitType.hashCode();
		}
	}

	/**
	 * A user tried to use a Premium feature.
	**/
	public static final class PremiumSourceFeature extends PremiumSource {


		/**
		 * The used feature.
		**/
		public PremiumFeature feature;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 445813541;

		/**
		 * A user tried to use a Premium feature.
		**/
		public PremiumSourceFeature() {}

		/**
		 * A user tried to use a Premium feature.
		 *
		 * @param feature The used feature.
		**/
		public PremiumSourceFeature(PremiumFeature feature) {
			this.feature = feature;
		}

		/**
		 * A user tried to use a Premium feature.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PremiumSourceFeature(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case PremiumFeatureIncreasedLimits.CONSTRUCTOR: this.feature = new PremiumFeatureIncreasedLimits(input); break;
					case PremiumFeatureIncreasedUploadFileSize.CONSTRUCTOR: this.feature = new PremiumFeatureIncreasedUploadFileSize(input); break;
					case PremiumFeatureImprovedDownloadSpeed.CONSTRUCTOR: this.feature = new PremiumFeatureImprovedDownloadSpeed(input); break;
					case PremiumFeatureVoiceRecognition.CONSTRUCTOR: this.feature = new PremiumFeatureVoiceRecognition(input); break;
					case PremiumFeatureDisabledAds.CONSTRUCTOR: this.feature = new PremiumFeatureDisabledAds(input); break;
					case PremiumFeatureUniqueReactions.CONSTRUCTOR: this.feature = new PremiumFeatureUniqueReactions(input); break;
					case PremiumFeatureUniqueStickers.CONSTRUCTOR: this.feature = new PremiumFeatureUniqueStickers(input); break;
					case PremiumFeatureCustomEmoji.CONSTRUCTOR: this.feature = new PremiumFeatureCustomEmoji(input); break;
					case PremiumFeatureAdvancedChatManagement.CONSTRUCTOR: this.feature = new PremiumFeatureAdvancedChatManagement(input); break;
					case PremiumFeatureProfileBadge.CONSTRUCTOR: this.feature = new PremiumFeatureProfileBadge(input); break;
					case PremiumFeatureEmojiStatus.CONSTRUCTOR: this.feature = new PremiumFeatureEmojiStatus(input); break;
					case PremiumFeatureAnimatedProfilePhoto.CONSTRUCTOR: this.feature = new PremiumFeatureAnimatedProfilePhoto(input); break;
					case PremiumFeatureForumTopicIcon.CONSTRUCTOR: this.feature = new PremiumFeatureForumTopicIcon(input); break;
					case PremiumFeatureAppIcons.CONSTRUCTOR: this.feature = new PremiumFeatureAppIcons(input); break;
					case PremiumFeatureRealTimeChatTranslation.CONSTRUCTOR: this.feature = new PremiumFeatureRealTimeChatTranslation(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PremiumSourceFeature.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PremiumSourceFeature.CONSTRUCTOR);
			if (this.feature == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.feature.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PremiumSourceFeature premiumSourceFeature = (PremiumSourceFeature) o;
			if (!Objects.equals(this.feature, premiumSourceFeature.feature)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.feature == null ? 0 : this.feature.hashCode();
		}
	}

	/**
	 * A user opened an internal link of the type
	 * internalLinkTypePremiumFeatures.
	**/
	public static final class PremiumSourceLink extends PremiumSource {


		/**
		 * The referrer from the link.
		**/
		public String referrer;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2135071132;

		/**
		 * A user opened an internal link of the type internalLinkTypePremiumFeatures.
		**/
		public PremiumSourceLink() {}

		/**
		 * A user opened an internal link of the type internalLinkTypePremiumFeatures.
		 *
		 * @param referrer The referrer from the link.
		**/
		public PremiumSourceLink(String referrer) {
			this.referrer = referrer;
		}

		/**
		 * A user opened an internal link of the type internalLinkTypePremiumFeatures.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PremiumSourceLink(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] referrerTmp = new byte[input.readInt()];
				input.readFully(referrerTmp);
				this.referrer = new String(referrerTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PremiumSourceLink.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PremiumSourceLink.CONSTRUCTOR);
			if (this.referrer == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] referrerTmp = this.referrer.getBytes(StandardCharsets.UTF_8);
				output.writeInt(referrerTmp.length);
				output.write(referrerTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PremiumSourceLink premiumSourceLink = (PremiumSourceLink) o;
			if (this.referrer != premiumSourceLink.referrer) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.referrer == null ? 0 : this.referrer.hashCode();
		}
	}

	/**
	 * A user opened the Premium features screen from settings.
	**/
	public static final class PremiumSourceSettings extends PremiumSource {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -285702859;

		/**
		 * A user opened the Premium features screen from settings.
		**/
		public PremiumSourceSettings() {}

		/**
		 * A user opened the Premium features screen from settings.
		 *
		**/

		/**
		 * A user opened the Premium features screen from settings.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PremiumSourceSettings(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PremiumSourceSettings.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PremiumSourceSettings.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PremiumSourceSettings.CONSTRUCTOR;
		}
	}

	/**
	 * Contains state of Telegram Premium subscription and promotion videos
	 * for Premium features.
	**/
	public static final class PremiumState extends Object {


		/**
		 * Text description of the state of the current Premium subscription; may be empty if the current user has no Telegram Premium subscription.
		**/
		public FormattedText state;

		/**
		 * The list of available options for buying Telegram Premium.
		**/
		public PremiumStatePaymentOption[] paymentOptions;

		/**
		 * The list of available promotion animations for Premium features.
		**/
		public PremiumFeaturePromotionAnimation[] animations;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1203513213;

		/**
		 * Contains state of Telegram Premium subscription and promotion videos for Premium features.
		**/
		public PremiumState() {}

		/**
		 * Contains state of Telegram Premium subscription and promotion videos for Premium features.
		 *
		 * @param state Text description of the state of the current Premium subscription; may be empty if the current user has no Telegram Premium subscription.
		 * @param paymentOptions The list of available options for buying Telegram Premium.
		 * @param animations The list of available promotion animations for Premium features.
		**/
		public PremiumState(FormattedText state,
				PremiumStatePaymentOption[] paymentOptions,
				PremiumFeaturePromotionAnimation[] animations) {
			this.state = state;
			this.paymentOptions = paymentOptions;
			this.animations = animations;
		}

		/**
		 * Contains state of Telegram Premium subscription and promotion videos for Premium features.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PremiumState(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (FormattedText.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.state = new FormattedText(input);
			}
			if (input.readBoolean()) {
				this.paymentOptions = new PremiumStatePaymentOption[input.readInt()];
				for (int i = 0; i < this.paymentOptions.length; i++) {
					if (PremiumStatePaymentOption.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.paymentOptions[i] = new PremiumStatePaymentOption(input);
				}
			}
			if (input.readBoolean()) {
				this.animations = new PremiumFeaturePromotionAnimation[input.readInt()];
				for (int i = 0; i < this.animations.length; i++) {
					if (PremiumFeaturePromotionAnimation.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.animations[i] = new PremiumFeaturePromotionAnimation(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PremiumState.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PremiumState.CONSTRUCTOR);
			if (this.state == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.state.serialize(output);
			}
			if (this.paymentOptions == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.paymentOptions.length);
				for (int i = 0; i < this.paymentOptions.length; i++) {
					this.paymentOptions[i].serialize(output);
				}
			}
			if (this.animations == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.animations.length);
				for (int i = 0; i < this.animations.length; i++) {
					this.animations[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PremiumState premiumState = (PremiumState) o;
			if (!Objects.equals(this.state, premiumState.state)) {
				return false;
			}
			if (!Arrays.equals(this.paymentOptions, premiumState.paymentOptions)) {
				return false;
			}
			if (!Arrays.equals(this.animations, premiumState.animations)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.state == null ? 0 : this.state.hashCode();
			result = result * 31 + (Arrays.hashCode(this.paymentOptions));
			result = result * 31 + (Arrays.hashCode(this.animations));
			return result;
		}
	}

	/**
	 * Describes an option for buying or upgrading Telegram Premium for self.
	**/
	public static final class PremiumStatePaymentOption extends Object {


		/**
		 * Information about the payment option.
		**/
		public PremiumPaymentOption paymentOption;

		/**
		 * True, if this is the currently used Telegram Premium subscription option.
		**/
		public boolean isCurrent;

		/**
		 * True, if the payment option can be used to upgrade the existing Telegram Premium subscription.
		**/
		public boolean isUpgrade;

		/**
		 * Identifier of the last in-store transaction for the currently used option.
		**/
		public String lastTransactionId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2097591673;

		/**
		 * Describes an option for buying or upgrading Telegram Premium for self.
		**/
		public PremiumStatePaymentOption() {}

		/**
		 * Describes an option for buying or upgrading Telegram Premium for self.
		 *
		 * @param paymentOption Information about the payment option.
		 * @param isCurrent True, if this is the currently used Telegram Premium subscription option.
		 * @param isUpgrade True, if the payment option can be used to upgrade the existing Telegram Premium subscription.
		 * @param lastTransactionId Identifier of the last in-store transaction for the currently used option.
		**/
		public PremiumStatePaymentOption(PremiumPaymentOption paymentOption,
				boolean isCurrent,
				boolean isUpgrade,
				String lastTransactionId) {
			this.paymentOption = paymentOption;
			this.isCurrent = isCurrent;
			this.isUpgrade = isUpgrade;
			this.lastTransactionId = lastTransactionId;
		}

		/**
		 * Describes an option for buying or upgrading Telegram Premium for self.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PremiumStatePaymentOption(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (PremiumPaymentOption.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.paymentOption = new PremiumPaymentOption(input);
			}
			this.isCurrent = input.readBoolean();
			this.isUpgrade = input.readBoolean();
			if (input.readBoolean()) {
				byte[] lastTransactionIdTmp = new byte[input.readInt()];
				input.readFully(lastTransactionIdTmp);
				this.lastTransactionId = new String(lastTransactionIdTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PremiumStatePaymentOption.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PremiumStatePaymentOption.CONSTRUCTOR);
			if (this.paymentOption == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.paymentOption.serialize(output);
			}
			output.writeBoolean(this.isCurrent);
			output.writeBoolean(this.isUpgrade);
			if (this.lastTransactionId == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] lastTransactionIdTmp = this.lastTransactionId.getBytes(StandardCharsets.UTF_8);
				output.writeInt(lastTransactionIdTmp.length);
				output.write(lastTransactionIdTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PremiumStatePaymentOption premiumStatePaymentOption = (PremiumStatePaymentOption) o;
			if (!Objects.equals(this.paymentOption, premiumStatePaymentOption.paymentOption)) {
				return false;
			}
			if (this.isCurrent != premiumStatePaymentOption.isCurrent) {
				return false;
			}
			if (this.isUpgrade != premiumStatePaymentOption.isUpgrade) {
				return false;
			}
			if (this.lastTransactionId != premiumStatePaymentOption.lastTransactionId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isCurrent);
			result = result * 31 + (this.paymentOption == null ? 0 : this.paymentOption.hashCode());
			result = result * 31 + (this.lastTransactionId == null ? 0 : this.lastTransactionId.hashCode());
			return result;
		}
	}

	/**
	 * Describes a user profile photo.
	**/
	public static final class ProfilePhoto extends Object {


		/**
		 * Photo identifier; 0 for an empty photo. Can be used to find a photo in a list of user profile photos.
		**/
		public long id;

		/**
		 * A small (160x160) user profile photo. The file can be downloaded only before the photo is changed.
		**/
		public File small;

		/**
		 * A big (640x640) user profile photo. The file can be downloaded only before the photo is changed.
		**/
		public File big;

		/**
		 * User profile photo minithumbnail; may be null.
		**/
		public Minithumbnail minithumbnail;

		/**
		 * True, if the photo has animated variant.
		**/
		public boolean hasAnimation;

		/**
		 * True, if the photo is visible only for the current user.
		**/
		public boolean isPersonal;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1025754018;

		/**
		 * Describes a user profile photo.
		**/
		public ProfilePhoto() {}

		/**
		 * Describes a user profile photo.
		 *
		 * @param id Photo identifier; 0 for an empty photo. Can be used to find a photo in a list of user profile photos.
		 * @param small A small (160x160) user profile photo. The file can be downloaded only before the photo is changed.
		 * @param big A big (640x640) user profile photo. The file can be downloaded only before the photo is changed.
		 * @param minithumbnail User profile photo minithumbnail; may be null.
		 * @param hasAnimation True, if the photo has animated variant.
		 * @param isPersonal True, if the photo is visible only for the current user.
		**/
		public ProfilePhoto(long id,
				File small,
				File big,
				Minithumbnail minithumbnail,
				boolean hasAnimation,
				boolean isPersonal) {
			this.id = id;
			this.small = small;
			this.big = big;
			this.minithumbnail = minithumbnail;
			this.hasAnimation = hasAnimation;
			this.isPersonal = isPersonal;
		}

		/**
		 * Describes a user profile photo.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ProfilePhoto(DataInput input) throws IOException {
			this.id = input.readLong();
			if (input.readBoolean()) {
				if (File.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.small = new File(input);
			}
			if (input.readBoolean()) {
				if (File.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.big = new File(input);
			}
			if (input.readBoolean()) {
				if (Minithumbnail.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.minithumbnail = new Minithumbnail(input);
			}
			this.hasAnimation = input.readBoolean();
			this.isPersonal = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ProfilePhoto.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ProfilePhoto.CONSTRUCTOR);
			output.writeLong(this.id);
			if (this.small == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.small.serialize(output);
			}
			if (this.big == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.big.serialize(output);
			}
			if (this.minithumbnail == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.minithumbnail.serialize(output);
			}
			output.writeBoolean(this.hasAnimation);
			output.writeBoolean(this.isPersonal);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ProfilePhoto profilePhoto = (ProfilePhoto) o;
			if (this.id != profilePhoto.id) {
				return false;
			}
			if (!Objects.equals(this.small, profilePhoto.small)) {
				return false;
			}
			if (!Objects.equals(this.big, profilePhoto.big)) {
				return false;
			}
			if (!Objects.equals(this.minithumbnail, profilePhoto.minithumbnail)) {
				return false;
			}
			if (this.hasAnimation != profilePhoto.hasAnimation) {
				return false;
			}
			if (this.isPersonal != profilePhoto.isPersonal) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.id);
			result = result * 31 + (this.small == null ? 0 : this.small.hashCode());
			result = result * 31 + (this.big == null ? 0 : this.big.hashCode());
			result = result * 31 + (this.minithumbnail == null ? 0 : this.minithumbnail.hashCode());
			return result;
		}
	}

	/**
	 * Represents a list of proxy servers.
	**/
	public static final class Proxies extends Object {


		/**
		 * List of proxy servers.
		**/
		public Proxy[] proxies;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1200447205;

		/**
		 * Represents a list of proxy servers.
		**/
		public Proxies() {}

		/**
		 * Represents a list of proxy servers.
		 *
		 * @param proxies List of proxy servers.
		**/
		public Proxies(Proxy[] proxies) {
			this.proxies = proxies;
		}

		/**
		 * Represents a list of proxy servers.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public Proxies(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.proxies = new Proxy[input.readInt()];
				for (int i = 0; i < this.proxies.length; i++) {
					if (Proxy.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.proxies[i] = new Proxy(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return Proxies.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(Proxies.CONSTRUCTOR);
			if (this.proxies == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.proxies.length);
				for (int i = 0; i < this.proxies.length; i++) {
					this.proxies[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			Proxies proxies = (Proxies) o;
			if (!Arrays.equals(this.proxies, proxies.proxies)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.proxies);
		}
	}

	/**
	 * Contains information about a proxy server.
	**/
	public static final class Proxy extends Object {


		/**
		 * Unique identifier of the proxy.
		**/
		public int id;

		/**
		 * Proxy server IP address.
		**/
		public String server;

		/**
		 * Proxy server port.
		**/
		public int port;

		/**
		 * Point in time (Unix timestamp) when the proxy was last used; 0 if never.
		**/
		public int lastUsedDate;

		/**
		 * True, if the proxy is enabled now.
		**/
		public boolean isEnabled;

		/**
		 * Type of the proxy.
		**/
		public ProxyType type;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 196049779;

		/**
		 * Contains information about a proxy server.
		**/
		public Proxy() {}

		/**
		 * Contains information about a proxy server.
		 *
		 * @param id Unique identifier of the proxy.
		 * @param server Proxy server IP address.
		 * @param port Proxy server port.
		 * @param lastUsedDate Point in time (Unix timestamp) when the proxy was last used; 0 if never.
		 * @param isEnabled True, if the proxy is enabled now.
		 * @param type Type of the proxy.
		**/
		public Proxy(int id,
				String server,
				int port,
				int lastUsedDate,
				boolean isEnabled,
				ProxyType type) {
			this.id = id;
			this.server = server;
			this.port = port;
			this.lastUsedDate = lastUsedDate;
			this.isEnabled = isEnabled;
			this.type = type;
		}

		/**
		 * Contains information about a proxy server.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public Proxy(DataInput input) throws IOException {
			this.id = input.readInt();
			if (input.readBoolean()) {
				byte[] serverTmp = new byte[input.readInt()];
				input.readFully(serverTmp);
				this.server = new String(serverTmp, StandardCharsets.UTF_8);
			}
			this.port = input.readInt();
			this.lastUsedDate = input.readInt();
			this.isEnabled = input.readBoolean();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ProxyTypeSocks5.CONSTRUCTOR: this.type = new ProxyTypeSocks5(input); break;
					case ProxyTypeHttp.CONSTRUCTOR: this.type = new ProxyTypeHttp(input); break;
					case ProxyTypeMtproto.CONSTRUCTOR: this.type = new ProxyTypeMtproto(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return Proxy.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(Proxy.CONSTRUCTOR);
			output.writeInt(this.id);
			if (this.server == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] serverTmp = this.server.getBytes(StandardCharsets.UTF_8);
				output.writeInt(serverTmp.length);
				output.write(serverTmp);
			}
			output.writeInt(this.port);
			output.writeInt(this.lastUsedDate);
			output.writeBoolean(this.isEnabled);
			if (this.type == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.type.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			Proxy proxy = (Proxy) o;
			if (this.id != proxy.id) {
				return false;
			}
			if (this.server != proxy.server) {
				return false;
			}
			if (this.port != proxy.port) {
				return false;
			}
			if (this.lastUsedDate != proxy.lastUsedDate) {
				return false;
			}
			if (this.isEnabled != proxy.isEnabled) {
				return false;
			}
			if (!Objects.equals(this.type, proxy.type)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.id);
			result = result * 31 + (this.server == null ? 0 : this.server.hashCode());
			result = result * 31 + (this.type == null ? 0 : this.type.hashCode());
			return result;
		}
	}

	/**
	 * A SOCKS5 proxy server.
	**/
	public static final class ProxyTypeSocks5 extends ProxyType {


		/**
		 * Username for logging in; may be empty.
		**/
		public String username;

		/**
		 * Password for logging in; may be empty.
		**/
		public String password;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -890027341;

		/**
		 * A SOCKS5 proxy server.
		**/
		public ProxyTypeSocks5() {}

		/**
		 * A SOCKS5 proxy server.
		 *
		 * @param username Username for logging in; may be empty.
		 * @param password Password for logging in; may be empty.
		**/
		public ProxyTypeSocks5(String username, String password) {
			this.username = username;
			this.password = password;
		}

		/**
		 * A SOCKS5 proxy server.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ProxyTypeSocks5(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] usernameTmp = new byte[input.readInt()];
				input.readFully(usernameTmp);
				this.username = new String(usernameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] passwordTmp = new byte[input.readInt()];
				input.readFully(passwordTmp);
				this.password = new String(passwordTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ProxyTypeSocks5.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ProxyTypeSocks5.CONSTRUCTOR);
			if (this.username == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] usernameTmp = this.username.getBytes(StandardCharsets.UTF_8);
				output.writeInt(usernameTmp.length);
				output.write(usernameTmp);
			}
			if (this.password == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] passwordTmp = this.password.getBytes(StandardCharsets.UTF_8);
				output.writeInt(passwordTmp.length);
				output.write(passwordTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ProxyTypeSocks5 proxyTypeSocks5 = (ProxyTypeSocks5) o;
			if (this.username != proxyTypeSocks5.username) {
				return false;
			}
			if (this.password != proxyTypeSocks5.password) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.username == null ? 0 : this.username.hashCode();
			result = result * 31 + (this.password == null ? 0 : this.password.hashCode());
			return result;
		}
	}

	/**
	 * A HTTP transparent proxy server.
	**/
	public static final class ProxyTypeHttp extends ProxyType {


		/**
		 * Username for logging in; may be empty.
		**/
		public String username;

		/**
		 * Password for logging in; may be empty.
		**/
		public String password;

		/**
		 * Pass true if the proxy supports only HTTP requests and doesn&#039;t support transparent TCP connections via HTTP CONNECT method.
		**/
		public boolean httpOnly;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1547188361;

		/**
		 * A HTTP transparent proxy server.
		**/
		public ProxyTypeHttp() {}

		/**
		 * A HTTP transparent proxy server.
		 *
		 * @param username Username for logging in; may be empty.
		 * @param password Password for logging in; may be empty.
		 * @param httpOnly Pass true if the proxy supports only HTTP requests and doesn&#039;t support transparent TCP connections via HTTP CONNECT method.
		**/
		public ProxyTypeHttp(String username, String password, boolean httpOnly) {
			this.username = username;
			this.password = password;
			this.httpOnly = httpOnly;
		}

		/**
		 * A HTTP transparent proxy server.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ProxyTypeHttp(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] usernameTmp = new byte[input.readInt()];
				input.readFully(usernameTmp);
				this.username = new String(usernameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] passwordTmp = new byte[input.readInt()];
				input.readFully(passwordTmp);
				this.password = new String(passwordTmp, StandardCharsets.UTF_8);
			}
			this.httpOnly = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ProxyTypeHttp.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ProxyTypeHttp.CONSTRUCTOR);
			if (this.username == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] usernameTmp = this.username.getBytes(StandardCharsets.UTF_8);
				output.writeInt(usernameTmp.length);
				output.write(usernameTmp);
			}
			if (this.password == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] passwordTmp = this.password.getBytes(StandardCharsets.UTF_8);
				output.writeInt(passwordTmp.length);
				output.write(passwordTmp);
			}
			output.writeBoolean(this.httpOnly);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ProxyTypeHttp proxyTypeHttp = (ProxyTypeHttp) o;
			if (this.username != proxyTypeHttp.username) {
				return false;
			}
			if (this.password != proxyTypeHttp.password) {
				return false;
			}
			if (this.httpOnly != proxyTypeHttp.httpOnly) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.httpOnly);
			result = result * 31 + (this.username == null ? 0 : this.username.hashCode());
			result = result * 31 + (this.password == null ? 0 : this.password.hashCode());
			return result;
		}
	}

	/**
	 * An MTProto proxy server.
	**/
	public static final class ProxyTypeMtproto extends ProxyType {


		/**
		 * The proxy&#039;s secret in hexadecimal encoding.
		**/
		public String secret;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1964826627;

		/**
		 * An MTProto proxy server.
		**/
		public ProxyTypeMtproto() {}

		/**
		 * An MTProto proxy server.
		 *
		 * @param secret The proxy&#039;s secret in hexadecimal encoding.
		**/
		public ProxyTypeMtproto(String secret) {
			this.secret = secret;
		}

		/**
		 * An MTProto proxy server.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ProxyTypeMtproto(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] secretTmp = new byte[input.readInt()];
				input.readFully(secretTmp);
				this.secret = new String(secretTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ProxyTypeMtproto.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ProxyTypeMtproto.CONSTRUCTOR);
			if (this.secret == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] secretTmp = this.secret.getBytes(StandardCharsets.UTF_8);
				output.writeInt(secretTmp.length);
				output.write(secretTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ProxyTypeMtproto proxyTypeMtproto = (ProxyTypeMtproto) o;
			if (this.secret != proxyTypeMtproto.secret) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.secret == null ? 0 : this.secret.hashCode();
		}
	}

	/**
	 * The chat is public, because it has an active username.
	**/
	public static final class PublicChatTypeHasUsername extends PublicChatType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 350789758;

		/**
		 * The chat is public, because it has an active username.
		**/
		public PublicChatTypeHasUsername() {}

		/**
		 * The chat is public, because it has an active username.
		 *
		**/

		/**
		 * The chat is public, because it has an active username.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PublicChatTypeHasUsername(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PublicChatTypeHasUsername.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PublicChatTypeHasUsername.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PublicChatTypeHasUsername.CONSTRUCTOR;
		}
	}

	/**
	 * The chat is public, because it is a location-based supergroup.
	**/
	public static final class PublicChatTypeIsLocationBased extends PublicChatType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1183735952;

		/**
		 * The chat is public, because it is a location-based supergroup.
		**/
		public PublicChatTypeIsLocationBased() {}

		/**
		 * The chat is public, because it is a location-based supergroup.
		 *
		**/

		/**
		 * The chat is public, because it is a location-based supergroup.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PublicChatTypeIsLocationBased(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PublicChatTypeIsLocationBased.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PublicChatTypeIsLocationBased.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PublicChatTypeIsLocationBased.CONSTRUCTOR;
		}
	}

	/**
	 * A general message with hidden content.
	**/
	public static final class PushMessageContentHidden extends PushMessageContent {


		/**
		 * True, if the message is a pinned message with the specified content.
		**/
		public boolean isPinned;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -316950436;

		/**
		 * A general message with hidden content.
		**/
		public PushMessageContentHidden() {}

		/**
		 * A general message with hidden content.
		 *
		 * @param isPinned True, if the message is a pinned message with the specified content.
		**/
		public PushMessageContentHidden(boolean isPinned) {
			this.isPinned = isPinned;
		}

		/**
		 * A general message with hidden content.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PushMessageContentHidden(DataInput input) throws IOException {
			this.isPinned = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PushMessageContentHidden.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PushMessageContentHidden.CONSTRUCTOR);
			output.writeBoolean(this.isPinned);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PushMessageContentHidden pushMessageContentHidden = (PushMessageContentHidden) o;
			if (this.isPinned != pushMessageContentHidden.isPinned) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Boolean.hashCode(this.isPinned);
		}
	}

	/**
	 * An animation message (GIF-style).
	**/
	public static final class PushMessageContentAnimation extends PushMessageContent {


		/**
		 * Message content; may be null.
		**/
		public Animation animation;

		/**
		 * Animation caption.
		**/
		public String caption;

		/**
		 * True, if the message is a pinned message with the specified content.
		**/
		public boolean isPinned;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1034215396;

		/**
		 * An animation message (GIF-style).
		**/
		public PushMessageContentAnimation() {}

		/**
		 * An animation message (GIF-style).
		 *
		 * @param animation Message content; may be null.
		 * @param caption Animation caption.
		 * @param isPinned True, if the message is a pinned message with the specified content.
		**/
		public PushMessageContentAnimation(Animation animation, String caption, boolean isPinned) {
			this.animation = animation;
			this.caption = caption;
			this.isPinned = isPinned;
		}

		/**
		 * An animation message (GIF-style).
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PushMessageContentAnimation(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Animation.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.animation = new Animation(input);
			}
			if (input.readBoolean()) {
				byte[] captionTmp = new byte[input.readInt()];
				input.readFully(captionTmp);
				this.caption = new String(captionTmp, StandardCharsets.UTF_8);
			}
			this.isPinned = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PushMessageContentAnimation.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PushMessageContentAnimation.CONSTRUCTOR);
			if (this.animation == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.animation.serialize(output);
			}
			if (this.caption == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] captionTmp = this.caption.getBytes(StandardCharsets.UTF_8);
				output.writeInt(captionTmp.length);
				output.write(captionTmp);
			}
			output.writeBoolean(this.isPinned);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PushMessageContentAnimation pushMessageContentAnimation = (PushMessageContentAnimation) o;
			if (!Objects.equals(this.animation, pushMessageContentAnimation.animation)) {
				return false;
			}
			if (this.caption != pushMessageContentAnimation.caption) {
				return false;
			}
			if (this.isPinned != pushMessageContentAnimation.isPinned) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isPinned);
			result = result * 31 + (this.animation == null ? 0 : this.animation.hashCode());
			result = result * 31 + (this.caption == null ? 0 : this.caption.hashCode());
			return result;
		}
	}

	/**
	 * An audio message.
	**/
	public static final class PushMessageContentAudio extends PushMessageContent {


		/**
		 * Message content; may be null.
		**/
		public Audio audio;

		/**
		 * True, if the message is a pinned message with the specified content.
		**/
		public boolean isPinned;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 381581426;

		/**
		 * An audio message.
		**/
		public PushMessageContentAudio() {}

		/**
		 * An audio message.
		 *
		 * @param audio Message content; may be null.
		 * @param isPinned True, if the message is a pinned message with the specified content.
		**/
		public PushMessageContentAudio(Audio audio, boolean isPinned) {
			this.audio = audio;
			this.isPinned = isPinned;
		}

		/**
		 * An audio message.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PushMessageContentAudio(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Audio.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.audio = new Audio(input);
			}
			this.isPinned = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PushMessageContentAudio.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PushMessageContentAudio.CONSTRUCTOR);
			if (this.audio == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.audio.serialize(output);
			}
			output.writeBoolean(this.isPinned);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PushMessageContentAudio pushMessageContentAudio = (PushMessageContentAudio) o;
			if (!Objects.equals(this.audio, pushMessageContentAudio.audio)) {
				return false;
			}
			if (this.isPinned != pushMessageContentAudio.isPinned) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isPinned);
			result = result * 31 + (this.audio == null ? 0 : this.audio.hashCode());
			return result;
		}
	}

	/**
	 * A message with a user contact.
	**/
	public static final class PushMessageContentContact extends PushMessageContent {


		/**
		 * Contact&#039;s name.
		**/
		public String name;

		/**
		 * True, if the message is a pinned message with the specified content.
		**/
		public boolean isPinned;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -12219820;

		/**
		 * A message with a user contact.
		**/
		public PushMessageContentContact() {}

		/**
		 * A message with a user contact.
		 *
		 * @param name Contact&#039;s name.
		 * @param isPinned True, if the message is a pinned message with the specified content.
		**/
		public PushMessageContentContact(String name, boolean isPinned) {
			this.name = name;
			this.isPinned = isPinned;
		}

		/**
		 * A message with a user contact.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PushMessageContentContact(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] nameTmp = new byte[input.readInt()];
				input.readFully(nameTmp);
				this.name = new String(nameTmp, StandardCharsets.UTF_8);
			}
			this.isPinned = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PushMessageContentContact.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PushMessageContentContact.CONSTRUCTOR);
			if (this.name == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nameTmp = this.name.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nameTmp.length);
				output.write(nameTmp);
			}
			output.writeBoolean(this.isPinned);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PushMessageContentContact pushMessageContentContact = (PushMessageContentContact) o;
			if (this.name != pushMessageContentContact.name) {
				return false;
			}
			if (this.isPinned != pushMessageContentContact.isPinned) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isPinned);
			result = result * 31 + (this.name == null ? 0 : this.name.hashCode());
			return result;
		}
	}

	/**
	 * A contact has registered with Telegram.
	**/
	public static final class PushMessageContentContactRegistered extends PushMessageContent {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -303962720;

		/**
		 * A contact has registered with Telegram.
		**/
		public PushMessageContentContactRegistered() {}

		/**
		 * A contact has registered with Telegram.
		 *
		**/

		/**
		 * A contact has registered with Telegram.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PushMessageContentContactRegistered(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PushMessageContentContactRegistered.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PushMessageContentContactRegistered.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PushMessageContentContactRegistered.CONSTRUCTOR;
		}
	}

	/**
	 * A document message (a general file).
	**/
	public static final class PushMessageContentDocument extends PushMessageContent {


		/**
		 * Message content; may be null.
		**/
		public Document document;

		/**
		 * True, if the message is a pinned message with the specified content.
		**/
		public boolean isPinned;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -458379775;

		/**
		 * A document message (a general file).
		**/
		public PushMessageContentDocument() {}

		/**
		 * A document message (a general file).
		 *
		 * @param document Message content; may be null.
		 * @param isPinned True, if the message is a pinned message with the specified content.
		**/
		public PushMessageContentDocument(Document document, boolean isPinned) {
			this.document = document;
			this.isPinned = isPinned;
		}

		/**
		 * A document message (a general file).
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PushMessageContentDocument(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Document.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.document = new Document(input);
			}
			this.isPinned = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PushMessageContentDocument.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PushMessageContentDocument.CONSTRUCTOR);
			if (this.document == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.document.serialize(output);
			}
			output.writeBoolean(this.isPinned);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PushMessageContentDocument pushMessageContentDocument = (PushMessageContentDocument) o;
			if (!Objects.equals(this.document, pushMessageContentDocument.document)) {
				return false;
			}
			if (this.isPinned != pushMessageContentDocument.isPinned) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isPinned);
			result = result * 31 + (this.document == null ? 0 : this.document.hashCode());
			return result;
		}
	}

	/**
	 * A message with a game.
	**/
	public static final class PushMessageContentGame extends PushMessageContent {


		/**
		 * Game title, empty for pinned game message.
		**/
		public String title;

		/**
		 * True, if the message is a pinned message with the specified content.
		**/
		public boolean isPinned;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -515131109;

		/**
		 * A message with a game.
		**/
		public PushMessageContentGame() {}

		/**
		 * A message with a game.
		 *
		 * @param title Game title, empty for pinned game message.
		 * @param isPinned True, if the message is a pinned message with the specified content.
		**/
		public PushMessageContentGame(String title, boolean isPinned) {
			this.title = title;
			this.isPinned = isPinned;
		}

		/**
		 * A message with a game.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PushMessageContentGame(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
			this.isPinned = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PushMessageContentGame.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PushMessageContentGame.CONSTRUCTOR);
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
			output.writeBoolean(this.isPinned);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PushMessageContentGame pushMessageContentGame = (PushMessageContentGame) o;
			if (this.title != pushMessageContentGame.title) {
				return false;
			}
			if (this.isPinned != pushMessageContentGame.isPinned) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isPinned);
			result = result * 31 + (this.title == null ? 0 : this.title.hashCode());
			return result;
		}
	}

	/**
	 * A new high score was achieved in a game.
	**/
	public static final class PushMessageContentGameScore extends PushMessageContent {


		/**
		 * Game title, empty for pinned message.
		**/
		public String title;

		/**
		 * New score, 0 for pinned message.
		**/
		public int score;

		/**
		 * True, if the message is a pinned message with the specified content.
		**/
		public boolean isPinned;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 901303688;

		/**
		 * A new high score was achieved in a game.
		**/
		public PushMessageContentGameScore() {}

		/**
		 * A new high score was achieved in a game.
		 *
		 * @param title Game title, empty for pinned message.
		 * @param score New score, 0 for pinned message.
		 * @param isPinned True, if the message is a pinned message with the specified content.
		**/
		public PushMessageContentGameScore(String title, int score, boolean isPinned) {
			this.title = title;
			this.score = score;
			this.isPinned = isPinned;
		}

		/**
		 * A new high score was achieved in a game.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PushMessageContentGameScore(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
			this.score = input.readInt();
			this.isPinned = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PushMessageContentGameScore.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PushMessageContentGameScore.CONSTRUCTOR);
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
			output.writeInt(this.score);
			output.writeBoolean(this.isPinned);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PushMessageContentGameScore pushMessageContentGameScore = (PushMessageContentGameScore) o;
			if (this.title != pushMessageContentGameScore.title) {
				return false;
			}
			if (this.score != pushMessageContentGameScore.score) {
				return false;
			}
			if (this.isPinned != pushMessageContentGameScore.isPinned) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.score);
			result = result * 31 + (this.title == null ? 0 : this.title.hashCode());
			return result;
		}
	}

	/**
	 * A message with an invoice from a bot.
	**/
	public static final class PushMessageContentInvoice extends PushMessageContent {


		/**
		 * Product price.
		**/
		public String price;

		/**
		 * True, if the message is a pinned message with the specified content.
		**/
		public boolean isPinned;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1731687492;

		/**
		 * A message with an invoice from a bot.
		**/
		public PushMessageContentInvoice() {}

		/**
		 * A message with an invoice from a bot.
		 *
		 * @param price Product price.
		 * @param isPinned True, if the message is a pinned message with the specified content.
		**/
		public PushMessageContentInvoice(String price, boolean isPinned) {
			this.price = price;
			this.isPinned = isPinned;
		}

		/**
		 * A message with an invoice from a bot.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PushMessageContentInvoice(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] priceTmp = new byte[input.readInt()];
				input.readFully(priceTmp);
				this.price = new String(priceTmp, StandardCharsets.UTF_8);
			}
			this.isPinned = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PushMessageContentInvoice.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PushMessageContentInvoice.CONSTRUCTOR);
			if (this.price == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] priceTmp = this.price.getBytes(StandardCharsets.UTF_8);
				output.writeInt(priceTmp.length);
				output.write(priceTmp);
			}
			output.writeBoolean(this.isPinned);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PushMessageContentInvoice pushMessageContentInvoice = (PushMessageContentInvoice) o;
			if (this.price != pushMessageContentInvoice.price) {
				return false;
			}
			if (this.isPinned != pushMessageContentInvoice.isPinned) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isPinned);
			result = result * 31 + (this.price == null ? 0 : this.price.hashCode());
			return result;
		}
	}

	/**
	 * A message with a location.
	**/
	public static final class PushMessageContentLocation extends PushMessageContent {


		/**
		 * True, if the location is live.
		**/
		public boolean isLive;

		/**
		 * True, if the message is a pinned message with the specified content.
		**/
		public boolean isPinned;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1288005709;

		/**
		 * A message with a location.
		**/
		public PushMessageContentLocation() {}

		/**
		 * A message with a location.
		 *
		 * @param isLive True, if the location is live.
		 * @param isPinned True, if the message is a pinned message with the specified content.
		**/
		public PushMessageContentLocation(boolean isLive, boolean isPinned) {
			this.isLive = isLive;
			this.isPinned = isPinned;
		}

		/**
		 * A message with a location.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PushMessageContentLocation(DataInput input) throws IOException {
			this.isLive = input.readBoolean();
			this.isPinned = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PushMessageContentLocation.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PushMessageContentLocation.CONSTRUCTOR);
			output.writeBoolean(this.isLive);
			output.writeBoolean(this.isPinned);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PushMessageContentLocation pushMessageContentLocation = (PushMessageContentLocation) o;
			if (this.isLive != pushMessageContentLocation.isLive) {
				return false;
			}
			if (this.isPinned != pushMessageContentLocation.isPinned) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isLive);
			return result;
		}
	}

	/**
	 * A photo message.
	**/
	public static final class PushMessageContentPhoto extends PushMessageContent {


		/**
		 * Message content; may be null.
		**/
		public Photo photo;

		/**
		 * Photo caption.
		**/
		public String caption;

		/**
		 * True, if the photo is secret.
		**/
		public boolean isSecret;

		/**
		 * True, if the message is a pinned message with the specified content.
		**/
		public boolean isPinned;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 140631122;

		/**
		 * A photo message.
		**/
		public PushMessageContentPhoto() {}

		/**
		 * A photo message.
		 *
		 * @param photo Message content; may be null.
		 * @param caption Photo caption.
		 * @param isSecret True, if the photo is secret.
		 * @param isPinned True, if the message is a pinned message with the specified content.
		**/
		public PushMessageContentPhoto(Photo photo,
				String caption,
				boolean isSecret,
				boolean isPinned) {
			this.photo = photo;
			this.caption = caption;
			this.isSecret = isSecret;
			this.isPinned = isPinned;
		}

		/**
		 * A photo message.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PushMessageContentPhoto(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Photo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.photo = new Photo(input);
			}
			if (input.readBoolean()) {
				byte[] captionTmp = new byte[input.readInt()];
				input.readFully(captionTmp);
				this.caption = new String(captionTmp, StandardCharsets.UTF_8);
			}
			this.isSecret = input.readBoolean();
			this.isPinned = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PushMessageContentPhoto.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PushMessageContentPhoto.CONSTRUCTOR);
			if (this.photo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.photo.serialize(output);
			}
			if (this.caption == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] captionTmp = this.caption.getBytes(StandardCharsets.UTF_8);
				output.writeInt(captionTmp.length);
				output.write(captionTmp);
			}
			output.writeBoolean(this.isSecret);
			output.writeBoolean(this.isPinned);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PushMessageContentPhoto pushMessageContentPhoto = (PushMessageContentPhoto) o;
			if (!Objects.equals(this.photo, pushMessageContentPhoto.photo)) {
				return false;
			}
			if (this.caption != pushMessageContentPhoto.caption) {
				return false;
			}
			if (this.isSecret != pushMessageContentPhoto.isSecret) {
				return false;
			}
			if (this.isPinned != pushMessageContentPhoto.isPinned) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isSecret);
			result = result * 31 + (this.photo == null ? 0 : this.photo.hashCode());
			result = result * 31 + (this.caption == null ? 0 : this.caption.hashCode());
			return result;
		}
	}

	/**
	 * A message with a poll.
	**/
	public static final class PushMessageContentPoll extends PushMessageContent {


		/**
		 * Poll question.
		**/
		public String question;

		/**
		 * True, if the poll is regular and not in quiz mode.
		**/
		public boolean isRegular;

		/**
		 * True, if the message is a pinned message with the specified content.
		**/
		public boolean isPinned;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -44403654;

		/**
		 * A message with a poll.
		**/
		public PushMessageContentPoll() {}

		/**
		 * A message with a poll.
		 *
		 * @param question Poll question.
		 * @param isRegular True, if the poll is regular and not in quiz mode.
		 * @param isPinned True, if the message is a pinned message with the specified content.
		**/
		public PushMessageContentPoll(String question, boolean isRegular, boolean isPinned) {
			this.question = question;
			this.isRegular = isRegular;
			this.isPinned = isPinned;
		}

		/**
		 * A message with a poll.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PushMessageContentPoll(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] questionTmp = new byte[input.readInt()];
				input.readFully(questionTmp);
				this.question = new String(questionTmp, StandardCharsets.UTF_8);
			}
			this.isRegular = input.readBoolean();
			this.isPinned = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PushMessageContentPoll.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PushMessageContentPoll.CONSTRUCTOR);
			if (this.question == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] questionTmp = this.question.getBytes(StandardCharsets.UTF_8);
				output.writeInt(questionTmp.length);
				output.write(questionTmp);
			}
			output.writeBoolean(this.isRegular);
			output.writeBoolean(this.isPinned);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PushMessageContentPoll pushMessageContentPoll = (PushMessageContentPoll) o;
			if (this.question != pushMessageContentPoll.question) {
				return false;
			}
			if (this.isRegular != pushMessageContentPoll.isRegular) {
				return false;
			}
			if (this.isPinned != pushMessageContentPoll.isPinned) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isRegular);
			result = result * 31 + (this.question == null ? 0 : this.question.hashCode());
			return result;
		}
	}

	/**
	 * A screenshot of a message in the chat has been taken.
	**/
	public static final class PushMessageContentScreenshotTaken extends PushMessageContent {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 214245369;

		/**
		 * A screenshot of a message in the chat has been taken.
		**/
		public PushMessageContentScreenshotTaken() {}

		/**
		 * A screenshot of a message in the chat has been taken.
		 *
		**/

		/**
		 * A screenshot of a message in the chat has been taken.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PushMessageContentScreenshotTaken(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PushMessageContentScreenshotTaken.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PushMessageContentScreenshotTaken.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PushMessageContentScreenshotTaken.CONSTRUCTOR;
		}
	}

	/**
	 * A message with a sticker.
	**/
	public static final class PushMessageContentSticker extends PushMessageContent {


		/**
		 * Message content; may be null.
		**/
		public Sticker sticker;

		/**
		 * Emoji corresponding to the sticker; may be empty.
		**/
		public String emoji;

		/**
		 * True, if the message is a pinned message with the specified content.
		**/
		public boolean isPinned;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1553513939;

		/**
		 * A message with a sticker.
		**/
		public PushMessageContentSticker() {}

		/**
		 * A message with a sticker.
		 *
		 * @param sticker Message content; may be null.
		 * @param emoji Emoji corresponding to the sticker; may be empty.
		 * @param isPinned True, if the message is a pinned message with the specified content.
		**/
		public PushMessageContentSticker(Sticker sticker, String emoji, boolean isPinned) {
			this.sticker = sticker;
			this.emoji = emoji;
			this.isPinned = isPinned;
		}

		/**
		 * A message with a sticker.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PushMessageContentSticker(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Sticker.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.sticker = new Sticker(input);
			}
			if (input.readBoolean()) {
				byte[] emojiTmp = new byte[input.readInt()];
				input.readFully(emojiTmp);
				this.emoji = new String(emojiTmp, StandardCharsets.UTF_8);
			}
			this.isPinned = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PushMessageContentSticker.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PushMessageContentSticker.CONSTRUCTOR);
			if (this.sticker == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.sticker.serialize(output);
			}
			if (this.emoji == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] emojiTmp = this.emoji.getBytes(StandardCharsets.UTF_8);
				output.writeInt(emojiTmp.length);
				output.write(emojiTmp);
			}
			output.writeBoolean(this.isPinned);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PushMessageContentSticker pushMessageContentSticker = (PushMessageContentSticker) o;
			if (!Objects.equals(this.sticker, pushMessageContentSticker.sticker)) {
				return false;
			}
			if (this.emoji != pushMessageContentSticker.emoji) {
				return false;
			}
			if (this.isPinned != pushMessageContentSticker.isPinned) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isPinned);
			result = result * 31 + (this.sticker == null ? 0 : this.sticker.hashCode());
			result = result * 31 + (this.emoji == null ? 0 : this.emoji.hashCode());
			return result;
		}
	}

	/**
	 * A text message.
	**/
	public static final class PushMessageContentText extends PushMessageContent {


		/**
		 * Message text.
		**/
		public String text;

		/**
		 * True, if the message is a pinned message with the specified content.
		**/
		public boolean isPinned;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 274587305;

		/**
		 * A text message.
		**/
		public PushMessageContentText() {}

		/**
		 * A text message.
		 *
		 * @param text Message text.
		 * @param isPinned True, if the message is a pinned message with the specified content.
		**/
		public PushMessageContentText(String text, boolean isPinned) {
			this.text = text;
			this.isPinned = isPinned;
		}

		/**
		 * A text message.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PushMessageContentText(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] textTmp = new byte[input.readInt()];
				input.readFully(textTmp);
				this.text = new String(textTmp, StandardCharsets.UTF_8);
			}
			this.isPinned = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PushMessageContentText.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PushMessageContentText.CONSTRUCTOR);
			if (this.text == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] textTmp = this.text.getBytes(StandardCharsets.UTF_8);
				output.writeInt(textTmp.length);
				output.write(textTmp);
			}
			output.writeBoolean(this.isPinned);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PushMessageContentText pushMessageContentText = (PushMessageContentText) o;
			if (this.text != pushMessageContentText.text) {
				return false;
			}
			if (this.isPinned != pushMessageContentText.isPinned) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isPinned);
			result = result * 31 + (this.text == null ? 0 : this.text.hashCode());
			return result;
		}
	}

	/**
	 * A video message.
	**/
	public static final class PushMessageContentVideo extends PushMessageContent {


		/**
		 * Message content; may be null.
		**/
		public Video video;

		/**
		 * Video caption.
		**/
		public String caption;

		/**
		 * True, if the video is secret.
		**/
		public boolean isSecret;

		/**
		 * True, if the message is a pinned message with the specified content.
		**/
		public boolean isPinned;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 310038831;

		/**
		 * A video message.
		**/
		public PushMessageContentVideo() {}

		/**
		 * A video message.
		 *
		 * @param video Message content; may be null.
		 * @param caption Video caption.
		 * @param isSecret True, if the video is secret.
		 * @param isPinned True, if the message is a pinned message with the specified content.
		**/
		public PushMessageContentVideo(Video video,
				String caption,
				boolean isSecret,
				boolean isPinned) {
			this.video = video;
			this.caption = caption;
			this.isSecret = isSecret;
			this.isPinned = isPinned;
		}

		/**
		 * A video message.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PushMessageContentVideo(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Video.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.video = new Video(input);
			}
			if (input.readBoolean()) {
				byte[] captionTmp = new byte[input.readInt()];
				input.readFully(captionTmp);
				this.caption = new String(captionTmp, StandardCharsets.UTF_8);
			}
			this.isSecret = input.readBoolean();
			this.isPinned = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PushMessageContentVideo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PushMessageContentVideo.CONSTRUCTOR);
			if (this.video == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.video.serialize(output);
			}
			if (this.caption == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] captionTmp = this.caption.getBytes(StandardCharsets.UTF_8);
				output.writeInt(captionTmp.length);
				output.write(captionTmp);
			}
			output.writeBoolean(this.isSecret);
			output.writeBoolean(this.isPinned);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PushMessageContentVideo pushMessageContentVideo = (PushMessageContentVideo) o;
			if (!Objects.equals(this.video, pushMessageContentVideo.video)) {
				return false;
			}
			if (this.caption != pushMessageContentVideo.caption) {
				return false;
			}
			if (this.isSecret != pushMessageContentVideo.isSecret) {
				return false;
			}
			if (this.isPinned != pushMessageContentVideo.isPinned) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isSecret);
			result = result * 31 + (this.video == null ? 0 : this.video.hashCode());
			result = result * 31 + (this.caption == null ? 0 : this.caption.hashCode());
			return result;
		}
	}

	/**
	 * A video note message.
	**/
	public static final class PushMessageContentVideoNote extends PushMessageContent {


		/**
		 * Message content; may be null.
		**/
		public VideoNote videoNote;

		/**
		 * True, if the message is a pinned message with the specified content.
		**/
		public boolean isPinned;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1122764417;

		/**
		 * A video note message.
		**/
		public PushMessageContentVideoNote() {}

		/**
		 * A video note message.
		 *
		 * @param videoNote Message content; may be null.
		 * @param isPinned True, if the message is a pinned message with the specified content.
		**/
		public PushMessageContentVideoNote(VideoNote videoNote, boolean isPinned) {
			this.videoNote = videoNote;
			this.isPinned = isPinned;
		}

		/**
		 * A video note message.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PushMessageContentVideoNote(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (VideoNote.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.videoNote = new VideoNote(input);
			}
			this.isPinned = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PushMessageContentVideoNote.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PushMessageContentVideoNote.CONSTRUCTOR);
			if (this.videoNote == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.videoNote.serialize(output);
			}
			output.writeBoolean(this.isPinned);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PushMessageContentVideoNote pushMessageContentVideoNote = (PushMessageContentVideoNote) o;
			if (!Objects.equals(this.videoNote, pushMessageContentVideoNote.videoNote)) {
				return false;
			}
			if (this.isPinned != pushMessageContentVideoNote.isPinned) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isPinned);
			result = result * 31 + (this.videoNote == null ? 0 : this.videoNote.hashCode());
			return result;
		}
	}

	/**
	 * A voice note message.
	**/
	public static final class PushMessageContentVoiceNote extends PushMessageContent {


		/**
		 * Message content; may be null.
		**/
		public VoiceNote voiceNote;

		/**
		 * True, if the message is a pinned message with the specified content.
		**/
		public boolean isPinned;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 88910987;

		/**
		 * A voice note message.
		**/
		public PushMessageContentVoiceNote() {}

		/**
		 * A voice note message.
		 *
		 * @param voiceNote Message content; may be null.
		 * @param isPinned True, if the message is a pinned message with the specified content.
		**/
		public PushMessageContentVoiceNote(VoiceNote voiceNote, boolean isPinned) {
			this.voiceNote = voiceNote;
			this.isPinned = isPinned;
		}

		/**
		 * A voice note message.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PushMessageContentVoiceNote(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (VoiceNote.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.voiceNote = new VoiceNote(input);
			}
			this.isPinned = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PushMessageContentVoiceNote.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PushMessageContentVoiceNote.CONSTRUCTOR);
			if (this.voiceNote == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.voiceNote.serialize(output);
			}
			output.writeBoolean(this.isPinned);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PushMessageContentVoiceNote pushMessageContentVoiceNote = (PushMessageContentVoiceNote) o;
			if (!Objects.equals(this.voiceNote, pushMessageContentVoiceNote.voiceNote)) {
				return false;
			}
			if (this.isPinned != pushMessageContentVoiceNote.isPinned) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isPinned);
			result = result * 31 + (this.voiceNote == null ? 0 : this.voiceNote.hashCode());
			return result;
		}
	}

	/**
	 * A newly created basic group.
	**/
	public static final class PushMessageContentBasicGroupChatCreate extends PushMessageContent {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2114855172;

		/**
		 * A newly created basic group.
		**/
		public PushMessageContentBasicGroupChatCreate() {}

		/**
		 * A newly created basic group.
		 *
		**/

		/**
		 * A newly created basic group.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PushMessageContentBasicGroupChatCreate(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PushMessageContentBasicGroupChatCreate.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PushMessageContentBasicGroupChatCreate.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PushMessageContentBasicGroupChatCreate.CONSTRUCTOR;
		}
	}

	/**
	 * New chat members were invited to a group.
	**/
	public static final class PushMessageContentChatAddMembers extends PushMessageContent {


		/**
		 * Name of the added member.
		**/
		public String memberName;

		/**
		 * True, if the current user was added to the group.
		**/
		public boolean isCurrentUser;

		/**
		 * True, if the user has returned to the group themselves.
		**/
		public boolean isReturned;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1087145158;

		/**
		 * New chat members were invited to a group.
		**/
		public PushMessageContentChatAddMembers() {}

		/**
		 * New chat members were invited to a group.
		 *
		 * @param memberName Name of the added member.
		 * @param isCurrentUser True, if the current user was added to the group.
		 * @param isReturned True, if the user has returned to the group themselves.
		**/
		public PushMessageContentChatAddMembers(String memberName, boolean isCurrentUser, boolean isReturned) {
			this.memberName = memberName;
			this.isCurrentUser = isCurrentUser;
			this.isReturned = isReturned;
		}

		/**
		 * New chat members were invited to a group.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PushMessageContentChatAddMembers(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] memberNameTmp = new byte[input.readInt()];
				input.readFully(memberNameTmp);
				this.memberName = new String(memberNameTmp, StandardCharsets.UTF_8);
			}
			this.isCurrentUser = input.readBoolean();
			this.isReturned = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PushMessageContentChatAddMembers.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PushMessageContentChatAddMembers.CONSTRUCTOR);
			if (this.memberName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] memberNameTmp = this.memberName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(memberNameTmp.length);
				output.write(memberNameTmp);
			}
			output.writeBoolean(this.isCurrentUser);
			output.writeBoolean(this.isReturned);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PushMessageContentChatAddMembers pushMessageContentChatAddMembers = (PushMessageContentChatAddMembers) o;
			if (this.memberName != pushMessageContentChatAddMembers.memberName) {
				return false;
			}
			if (this.isCurrentUser != pushMessageContentChatAddMembers.isCurrentUser) {
				return false;
			}
			if (this.isReturned != pushMessageContentChatAddMembers.isReturned) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isCurrentUser);
			result = result * 31 + (this.memberName == null ? 0 : this.memberName.hashCode());
			return result;
		}
	}

	/**
	 * A chat photo was edited.
	**/
	public static final class PushMessageContentChatChangePhoto extends PushMessageContent {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1114222051;

		/**
		 * A chat photo was edited.
		**/
		public PushMessageContentChatChangePhoto() {}

		/**
		 * A chat photo was edited.
		 *
		**/

		/**
		 * A chat photo was edited.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PushMessageContentChatChangePhoto(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PushMessageContentChatChangePhoto.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PushMessageContentChatChangePhoto.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PushMessageContentChatChangePhoto.CONSTRUCTOR;
		}
	}

	/**
	 * A chat title was edited.
	**/
	public static final class PushMessageContentChatChangeTitle extends PushMessageContent {


		/**
		 * New chat title.
		**/
		public String title;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1964902749;

		/**
		 * A chat title was edited.
		**/
		public PushMessageContentChatChangeTitle() {}

		/**
		 * A chat title was edited.
		 *
		 * @param title New chat title.
		**/
		public PushMessageContentChatChangeTitle(String title) {
			this.title = title;
		}

		/**
		 * A chat title was edited.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PushMessageContentChatChangeTitle(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PushMessageContentChatChangeTitle.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PushMessageContentChatChangeTitle.CONSTRUCTOR);
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PushMessageContentChatChangeTitle pushMessageContentChatChangeTitle = (PushMessageContentChatChangeTitle) o;
			if (this.title != pushMessageContentChatChangeTitle.title) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.title == null ? 0 : this.title.hashCode();
		}
	}

	/**
	 * A chat background was edited.
	**/
	public static final class PushMessageContentChatSetBackground extends PushMessageContent {


		/**
		 * True, if the set background is the same as the background of the current user.
		**/
		public boolean isSame;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1490331933;

		/**
		 * A chat background was edited.
		**/
		public PushMessageContentChatSetBackground() {}

		/**
		 * A chat background was edited.
		 *
		 * @param isSame True, if the set background is the same as the background of the current user.
		**/
		public PushMessageContentChatSetBackground(boolean isSame) {
			this.isSame = isSame;
		}

		/**
		 * A chat background was edited.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PushMessageContentChatSetBackground(DataInput input) throws IOException {
			this.isSame = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PushMessageContentChatSetBackground.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PushMessageContentChatSetBackground.CONSTRUCTOR);
			output.writeBoolean(this.isSame);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PushMessageContentChatSetBackground pushMessageContentChatSetBackground = (PushMessageContentChatSetBackground) o;
			if (this.isSame != pushMessageContentChatSetBackground.isSame) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Boolean.hashCode(this.isSame);
		}
	}

	/**
	 * A chat theme was edited.
	**/
	public static final class PushMessageContentChatSetTheme extends PushMessageContent {


		/**
		 * If non-empty, name of a new theme, set for the chat. Otherwise, the chat theme was reset to the default one.
		**/
		public String themeName;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 173882216;

		/**
		 * A chat theme was edited.
		**/
		public PushMessageContentChatSetTheme() {}

		/**
		 * A chat theme was edited.
		 *
		 * @param themeName If non-empty, name of a new theme, set for the chat. Otherwise, the chat theme was reset to the default one.
		**/
		public PushMessageContentChatSetTheme(String themeName) {
			this.themeName = themeName;
		}

		/**
		 * A chat theme was edited.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PushMessageContentChatSetTheme(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] themeNameTmp = new byte[input.readInt()];
				input.readFully(themeNameTmp);
				this.themeName = new String(themeNameTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PushMessageContentChatSetTheme.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PushMessageContentChatSetTheme.CONSTRUCTOR);
			if (this.themeName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] themeNameTmp = this.themeName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(themeNameTmp.length);
				output.write(themeNameTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PushMessageContentChatSetTheme pushMessageContentChatSetTheme = (PushMessageContentChatSetTheme) o;
			if (this.themeName != pushMessageContentChatSetTheme.themeName) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.themeName == null ? 0 : this.themeName.hashCode();
		}
	}

	/**
	 * A chat member was deleted.
	**/
	public static final class PushMessageContentChatDeleteMember extends PushMessageContent {


		/**
		 * Name of the deleted member.
		**/
		public String memberName;

		/**
		 * True, if the current user was deleted from the group.
		**/
		public boolean isCurrentUser;

		/**
		 * True, if the user has left the group themselves.
		**/
		public boolean isLeft;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 598714783;

		/**
		 * A chat member was deleted.
		**/
		public PushMessageContentChatDeleteMember() {}

		/**
		 * A chat member was deleted.
		 *
		 * @param memberName Name of the deleted member.
		 * @param isCurrentUser True, if the current user was deleted from the group.
		 * @param isLeft True, if the user has left the group themselves.
		**/
		public PushMessageContentChatDeleteMember(String memberName, boolean isCurrentUser, boolean isLeft) {
			this.memberName = memberName;
			this.isCurrentUser = isCurrentUser;
			this.isLeft = isLeft;
		}

		/**
		 * A chat member was deleted.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PushMessageContentChatDeleteMember(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] memberNameTmp = new byte[input.readInt()];
				input.readFully(memberNameTmp);
				this.memberName = new String(memberNameTmp, StandardCharsets.UTF_8);
			}
			this.isCurrentUser = input.readBoolean();
			this.isLeft = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PushMessageContentChatDeleteMember.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PushMessageContentChatDeleteMember.CONSTRUCTOR);
			if (this.memberName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] memberNameTmp = this.memberName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(memberNameTmp.length);
				output.write(memberNameTmp);
			}
			output.writeBoolean(this.isCurrentUser);
			output.writeBoolean(this.isLeft);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PushMessageContentChatDeleteMember pushMessageContentChatDeleteMember = (PushMessageContentChatDeleteMember) o;
			if (this.memberName != pushMessageContentChatDeleteMember.memberName) {
				return false;
			}
			if (this.isCurrentUser != pushMessageContentChatDeleteMember.isCurrentUser) {
				return false;
			}
			if (this.isLeft != pushMessageContentChatDeleteMember.isLeft) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isCurrentUser);
			result = result * 31 + (this.memberName == null ? 0 : this.memberName.hashCode());
			return result;
		}
	}

	/**
	 * A new member joined the chat via an invite link.
	**/
	public static final class PushMessageContentChatJoinByLink extends PushMessageContent {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1553719113;

		/**
		 * A new member joined the chat via an invite link.
		**/
		public PushMessageContentChatJoinByLink() {}

		/**
		 * A new member joined the chat via an invite link.
		 *
		**/

		/**
		 * A new member joined the chat via an invite link.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PushMessageContentChatJoinByLink(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PushMessageContentChatJoinByLink.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PushMessageContentChatJoinByLink.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PushMessageContentChatJoinByLink.CONSTRUCTOR;
		}
	}

	/**
	 * A new member was accepted to the chat by an administrator.
	**/
	public static final class PushMessageContentChatJoinByRequest extends PushMessageContent {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -205823627;

		/**
		 * A new member was accepted to the chat by an administrator.
		**/
		public PushMessageContentChatJoinByRequest() {}

		/**
		 * A new member was accepted to the chat by an administrator.
		 *
		**/

		/**
		 * A new member was accepted to the chat by an administrator.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PushMessageContentChatJoinByRequest(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PushMessageContentChatJoinByRequest.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PushMessageContentChatJoinByRequest.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PushMessageContentChatJoinByRequest.CONSTRUCTOR;
		}
	}

	/**
	 * A new recurrent payment was made by the current user.
	**/
	public static final class PushMessageContentRecurringPayment extends PushMessageContent {


		/**
		 * The paid amount.
		**/
		public String amount;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1619211802;

		/**
		 * A new recurrent payment was made by the current user.
		**/
		public PushMessageContentRecurringPayment() {}

		/**
		 * A new recurrent payment was made by the current user.
		 *
		 * @param amount The paid amount.
		**/
		public PushMessageContentRecurringPayment(String amount) {
			this.amount = amount;
		}

		/**
		 * A new recurrent payment was made by the current user.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PushMessageContentRecurringPayment(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] amountTmp = new byte[input.readInt()];
				input.readFully(amountTmp);
				this.amount = new String(amountTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PushMessageContentRecurringPayment.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PushMessageContentRecurringPayment.CONSTRUCTOR);
			if (this.amount == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] amountTmp = this.amount.getBytes(StandardCharsets.UTF_8);
				output.writeInt(amountTmp.length);
				output.write(amountTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PushMessageContentRecurringPayment pushMessageContentRecurringPayment = (PushMessageContentRecurringPayment) o;
			if (this.amount != pushMessageContentRecurringPayment.amount) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.amount == null ? 0 : this.amount.hashCode();
		}
	}

	/**
	 * A profile photo was suggested to the user.
	**/
	public static final class PushMessageContentSuggestProfilePhoto extends PushMessageContent {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2104225963;

		/**
		 * A profile photo was suggested to the user.
		**/
		public PushMessageContentSuggestProfilePhoto() {}

		/**
		 * A profile photo was suggested to the user.
		 *
		**/

		/**
		 * A profile photo was suggested to the user.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PushMessageContentSuggestProfilePhoto(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PushMessageContentSuggestProfilePhoto.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PushMessageContentSuggestProfilePhoto.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return PushMessageContentSuggestProfilePhoto.CONSTRUCTOR;
		}
	}

	/**
	 * A forwarded messages.
	**/
	public static final class PushMessageContentMessageForwards extends PushMessageContent {


		/**
		 * Number of forwarded messages.
		**/
		public int totalCount;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1913083876;

		/**
		 * A forwarded messages.
		**/
		public PushMessageContentMessageForwards() {}

		/**
		 * A forwarded messages.
		 *
		 * @param totalCount Number of forwarded messages.
		**/
		public PushMessageContentMessageForwards(int totalCount) {
			this.totalCount = totalCount;
		}

		/**
		 * A forwarded messages.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PushMessageContentMessageForwards(DataInput input) throws IOException {
			this.totalCount = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PushMessageContentMessageForwards.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PushMessageContentMessageForwards.CONSTRUCTOR);
			output.writeInt(this.totalCount);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PushMessageContentMessageForwards pushMessageContentMessageForwards = (PushMessageContentMessageForwards) o;
			if (this.totalCount != pushMessageContentMessageForwards.totalCount) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.totalCount);
		}
	}

	/**
	 * A media album.
	**/
	public static final class PushMessageContentMediaAlbum extends PushMessageContent {


		/**
		 * Number of messages in the album.
		**/
		public int totalCount;

		/**
		 * True, if the album has at least one photo.
		**/
		public boolean hasPhotos;

		/**
		 * True, if the album has at least one video file.
		**/
		public boolean hasVideos;

		/**
		 * True, if the album has at least one audio file.
		**/
		public boolean hasAudios;

		/**
		 * True, if the album has at least one document.
		**/
		public boolean hasDocuments;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -748426897;

		/**
		 * A media album.
		**/
		public PushMessageContentMediaAlbum() {}

		/**
		 * A media album.
		 *
		 * @param totalCount Number of messages in the album.
		 * @param hasPhotos True, if the album has at least one photo.
		 * @param hasVideos True, if the album has at least one video file.
		 * @param hasAudios True, if the album has at least one audio file.
		 * @param hasDocuments True, if the album has at least one document.
		**/
		public PushMessageContentMediaAlbum(int totalCount,
				boolean hasPhotos,
				boolean hasVideos,
				boolean hasAudios,
				boolean hasDocuments) {
			this.totalCount = totalCount;
			this.hasPhotos = hasPhotos;
			this.hasVideos = hasVideos;
			this.hasAudios = hasAudios;
			this.hasDocuments = hasDocuments;
		}

		/**
		 * A media album.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PushMessageContentMediaAlbum(DataInput input) throws IOException {
			this.totalCount = input.readInt();
			this.hasPhotos = input.readBoolean();
			this.hasVideos = input.readBoolean();
			this.hasAudios = input.readBoolean();
			this.hasDocuments = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PushMessageContentMediaAlbum.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PushMessageContentMediaAlbum.CONSTRUCTOR);
			output.writeInt(this.totalCount);
			output.writeBoolean(this.hasPhotos);
			output.writeBoolean(this.hasVideos);
			output.writeBoolean(this.hasAudios);
			output.writeBoolean(this.hasDocuments);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PushMessageContentMediaAlbum pushMessageContentMediaAlbum = (PushMessageContentMediaAlbum) o;
			if (this.totalCount != pushMessageContentMediaAlbum.totalCount) {
				return false;
			}
			if (this.hasPhotos != pushMessageContentMediaAlbum.hasPhotos) {
				return false;
			}
			if (this.hasVideos != pushMessageContentMediaAlbum.hasVideos) {
				return false;
			}
			if (this.hasAudios != pushMessageContentMediaAlbum.hasAudios) {
				return false;
			}
			if (this.hasDocuments != pushMessageContentMediaAlbum.hasDocuments) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.totalCount);
			return result;
		}
	}

	/**
	 * Contains a globally unique push receiver identifier, which can be
	 * used to identify which account has received a push notification.
	**/
	public static final class PushReceiverId extends Object {


		/**
		 * The globally unique identifier of push notification subscription.
		**/
		public long id;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 371056428;

		/**
		 * Contains a globally unique push receiver identifier, which can be used to identify which account has received a push notification.
		**/
		public PushReceiverId() {}

		/**
		 * Contains a globally unique push receiver identifier, which can be used to identify which account has received a push notification.
		 *
		 * @param id The globally unique identifier of push notification subscription.
		**/
		public PushReceiverId(long id) {
			this.id = id;
		}

		/**
		 * Contains a globally unique push receiver identifier, which can be used to identify which account has received a push notification.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PushReceiverId(DataInput input) throws IOException {
			this.id = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PushReceiverId.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PushReceiverId.CONSTRUCTOR);
			output.writeLong(this.id);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PushReceiverId pushReceiverId = (PushReceiverId) o;
			if (this.id != pushReceiverId.id) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.id);
		}
	}

	/**
	 * A reaction with an emoji.
	**/
	public static final class ReactionTypeEmoji extends ReactionType {


		/**
		 * Text representation of the reaction.
		**/
		public String emoji;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1942084920;

		/**
		 * A reaction with an emoji.
		**/
		public ReactionTypeEmoji() {}

		/**
		 * A reaction with an emoji.
		 *
		 * @param emoji Text representation of the reaction.
		**/
		public ReactionTypeEmoji(String emoji) {
			this.emoji = emoji;
		}

		/**
		 * A reaction with an emoji.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ReactionTypeEmoji(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] emojiTmp = new byte[input.readInt()];
				input.readFully(emojiTmp);
				this.emoji = new String(emojiTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ReactionTypeEmoji.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ReactionTypeEmoji.CONSTRUCTOR);
			if (this.emoji == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] emojiTmp = this.emoji.getBytes(StandardCharsets.UTF_8);
				output.writeInt(emojiTmp.length);
				output.write(emojiTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ReactionTypeEmoji reactionTypeEmoji = (ReactionTypeEmoji) o;
			if (this.emoji != reactionTypeEmoji.emoji) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.emoji == null ? 0 : this.emoji.hashCode();
		}
	}

	/**
	 * A reaction with a custom emoji.
	**/
	public static final class ReactionTypeCustomEmoji extends ReactionType {


		/**
		 * Unique identifier of the custom emoji.
		**/
		public long customEmojiId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -989117709;

		/**
		 * A reaction with a custom emoji.
		**/
		public ReactionTypeCustomEmoji() {}

		/**
		 * A reaction with a custom emoji.
		 *
		 * @param customEmojiId Unique identifier of the custom emoji.
		**/
		public ReactionTypeCustomEmoji(long customEmojiId) {
			this.customEmojiId = customEmojiId;
		}

		/**
		 * A reaction with a custom emoji.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ReactionTypeCustomEmoji(DataInput input) throws IOException {
			this.customEmojiId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ReactionTypeCustomEmoji.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ReactionTypeCustomEmoji.CONSTRUCTOR);
			output.writeLong(this.customEmojiId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ReactionTypeCustomEmoji reactionTypeCustomEmoji = (ReactionTypeCustomEmoji) o;
			if (this.customEmojiId != reactionTypeCustomEmoji.customEmojiId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.customEmojiId);
		}
	}

	/**
	 * Describes a recommended chat folder.
	**/
	public static final class RecommendedChatFolder extends Object {


		/**
		 * The chat folder.
		**/
		public ChatFolder folder;

		/**
		 * Chat folder description.
		**/
		public String description;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2116569930;

		/**
		 * Describes a recommended chat folder.
		**/
		public RecommendedChatFolder() {}

		/**
		 * Describes a recommended chat folder.
		 *
		 * @param folder The chat folder.
		 * @param description Chat folder description.
		**/
		public RecommendedChatFolder(ChatFolder folder, String description) {
			this.folder = folder;
			this.description = description;
		}

		/**
		 * Describes a recommended chat folder.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RecommendedChatFolder(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (ChatFolder.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.folder = new ChatFolder(input);
			}
			if (input.readBoolean()) {
				byte[] descriptionTmp = new byte[input.readInt()];
				input.readFully(descriptionTmp);
				this.description = new String(descriptionTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RecommendedChatFolder.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RecommendedChatFolder.CONSTRUCTOR);
			if (this.folder == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.folder.serialize(output);
			}
			if (this.description == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] descriptionTmp = this.description.getBytes(StandardCharsets.UTF_8);
				output.writeInt(descriptionTmp.length);
				output.write(descriptionTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			RecommendedChatFolder recommendedChatFolder = (RecommendedChatFolder) o;
			if (!Objects.equals(this.folder, recommendedChatFolder.folder)) {
				return false;
			}
			if (this.description != recommendedChatFolder.description) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.folder == null ? 0 : this.folder.hashCode();
			result = result * 31 + (this.description == null ? 0 : this.description.hashCode());
			return result;
		}
	}

	/**
	 * Contains a list of recommended chat folders.
	**/
	public static final class RecommendedChatFolders extends Object {


		/**
		 * List of recommended chat folders.
		**/
		public RecommendedChatFolder[] chatFolders;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -739217656;

		/**
		 * Contains a list of recommended chat folders.
		**/
		public RecommendedChatFolders() {}

		/**
		 * Contains a list of recommended chat folders.
		 *
		 * @param chatFolders List of recommended chat folders.
		**/
		public RecommendedChatFolders(RecommendedChatFolder[] chatFolders) {
			this.chatFolders = chatFolders;
		}

		/**
		 * Contains a list of recommended chat folders.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RecommendedChatFolders(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.chatFolders = new RecommendedChatFolder[input.readInt()];
				for (int i = 0; i < this.chatFolders.length; i++) {
					if (RecommendedChatFolder.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.chatFolders[i] = new RecommendedChatFolder(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RecommendedChatFolders.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RecommendedChatFolders.CONSTRUCTOR);
			if (this.chatFolders == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.chatFolders.length);
				for (int i = 0; i < this.chatFolders.length; i++) {
					this.chatFolders[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			RecommendedChatFolders recommendedChatFolders = (RecommendedChatFolders) o;
			if (!Arrays.equals(this.chatFolders, recommendedChatFolders.chatFolders)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.chatFolders);
		}
	}

	/**
	 * Contains information about the current recovery email address.
	**/
	public static final class RecoveryEmailAddress extends Object {


		/**
		 * Recovery email address.
		**/
		public String recoveryEmailAddress;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1290526187;

		/**
		 * Contains information about the current recovery email address.
		**/
		public RecoveryEmailAddress() {}

		/**
		 * Contains information about the current recovery email address.
		 *
		 * @param recoveryEmailAddress Recovery email address.
		**/
		public RecoveryEmailAddress(String recoveryEmailAddress) {
			this.recoveryEmailAddress = recoveryEmailAddress;
		}

		/**
		 * Contains information about the current recovery email address.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RecoveryEmailAddress(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] recoveryEmailAddressTmp = new byte[input.readInt()];
				input.readFully(recoveryEmailAddressTmp);
				this.recoveryEmailAddress = new String(recoveryEmailAddressTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RecoveryEmailAddress.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RecoveryEmailAddress.CONSTRUCTOR);
			if (this.recoveryEmailAddress == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] recoveryEmailAddressTmp = this.recoveryEmailAddress.getBytes(StandardCharsets.UTF_8);
				output.writeInt(recoveryEmailAddressTmp.length);
				output.write(recoveryEmailAddressTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			RecoveryEmailAddress recoveryEmailAddress = (RecoveryEmailAddress) o;
			if (this.recoveryEmailAddress != recoveryEmailAddress.recoveryEmailAddress) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.recoveryEmailAddress == null ? 0 : this.recoveryEmailAddress.hashCode();
		}
	}

	/**
	 * Represents a remote file.
	**/
	public static final class RemoteFile extends Object {


		/**
		 * Remote file identifier; may be empty. Can be used by the current user across application restarts or even from other devices. Uniquely identifies a file, but a file can have a lot of different valid identifiers. If the ID starts with &quot;http://&quot; or &quot;https://&quot;, it represents the HTTP URL of the file. TDLib is currently unable to download files if only their URL is known. If downloadFile/addFileToDownloads is called on such a file or if it is sent to a secret chat, TDLib starts a file generation process by sending updateFileGenerationStart to the application with the HTTP URL in the originalPath and &quot;#url#&quot; as the conversion string. Application must generate the file by downloading it to the specified location.
		**/
		public String id;

		/**
		 * Unique file identifier; may be empty if unknown. The unique file identifier which is the same for the same file even for different users and is persistent over time.
		**/
		public String uniqueId;

		/**
		 * True, if the file is currently being uploaded (or a remote copy is being generated by some other means).
		**/
		public boolean isUploadingActive;

		/**
		 * True, if a remote copy is fully available.
		**/
		public boolean isUploadingCompleted;

		/**
		 * Size of the remote available part of the file, in bytes; 0 if unknown.
		**/
		public long uploadedSize;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 747731030;

		/**
		 * Represents a remote file.
		**/
		public RemoteFile() {}

		/**
		 * Represents a remote file.
		 *
		 * @param id Remote file identifier; may be empty. Can be used by the current user across application restarts or even from other devices. Uniquely identifies a file, but a file can have a lot of different valid identifiers. If the ID starts with &quot;http://&quot; or &quot;https://&quot;, it represents the HTTP URL of the file. TDLib is currently unable to download files if only their URL is known. If downloadFile/addFileToDownloads is called on such a file or if it is sent to a secret chat, TDLib starts a file generation process by sending updateFileGenerationStart to the application with the HTTP URL in the originalPath and &quot;#url#&quot; as the conversion string. Application must generate the file by downloading it to the specified location.
		 * @param uniqueId Unique file identifier; may be empty if unknown. The unique file identifier which is the same for the same file even for different users and is persistent over time.
		 * @param isUploadingActive True, if the file is currently being uploaded (or a remote copy is being generated by some other means).
		 * @param isUploadingCompleted True, if a remote copy is fully available.
		 * @param uploadedSize Size of the remote available part of the file, in bytes; 0 if unknown.
		**/
		public RemoteFile(String id,
				String uniqueId,
				boolean isUploadingActive,
				boolean isUploadingCompleted,
				long uploadedSize) {
			this.id = id;
			this.uniqueId = uniqueId;
			this.isUploadingActive = isUploadingActive;
			this.isUploadingCompleted = isUploadingCompleted;
			this.uploadedSize = uploadedSize;
		}

		/**
		 * Represents a remote file.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RemoteFile(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] idTmp = new byte[input.readInt()];
				input.readFully(idTmp);
				this.id = new String(idTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] uniqueIdTmp = new byte[input.readInt()];
				input.readFully(uniqueIdTmp);
				this.uniqueId = new String(uniqueIdTmp, StandardCharsets.UTF_8);
			}
			this.isUploadingActive = input.readBoolean();
			this.isUploadingCompleted = input.readBoolean();
			this.uploadedSize = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RemoteFile.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RemoteFile.CONSTRUCTOR);
			if (this.id == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] idTmp = this.id.getBytes(StandardCharsets.UTF_8);
				output.writeInt(idTmp.length);
				output.write(idTmp);
			}
			if (this.uniqueId == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] uniqueIdTmp = this.uniqueId.getBytes(StandardCharsets.UTF_8);
				output.writeInt(uniqueIdTmp.length);
				output.write(uniqueIdTmp);
			}
			output.writeBoolean(this.isUploadingActive);
			output.writeBoolean(this.isUploadingCompleted);
			output.writeLong(this.uploadedSize);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			RemoteFile remoteFile = (RemoteFile) o;
			if (this.id != remoteFile.id) {
				return false;
			}
			if (this.uniqueId != remoteFile.uniqueId) {
				return false;
			}
			if (this.isUploadingActive != remoteFile.isUploadingActive) {
				return false;
			}
			if (this.isUploadingCompleted != remoteFile.isUploadingCompleted) {
				return false;
			}
			if (this.uploadedSize != remoteFile.uploadedSize) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isUploadingActive);
			result = result * 31 + (this.id == null ? 0 : this.id.hashCode());
			result = result * 31 + (this.uniqueId == null ? 0 : this.uniqueId.hashCode());
			return result;
		}
	}

	/**
	 * Instructs application to remove the keyboard once this message has
	 * been received. This kind of keyboard can&#039;t be received in an
	 * incoming message; instead, updateChatReplyMarkup with messageId == 0
	 * will be sent.
	**/
	public static final class ReplyMarkupRemoveKeyboard extends ReplyMarkup {


		/**
		 * True, if the keyboard is removed only for the mentioned users or the target user of a reply.
		**/
		public boolean isPersonal;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -691252879;

		/**
		 * Instructs application to remove the keyboard once this message has been received. This kind of keyboard can&#039;t be received in an incoming message; instead, updateChatReplyMarkup with messageId == 0 will be sent.
		**/
		public ReplyMarkupRemoveKeyboard() {}

		/**
		 * Instructs application to remove the keyboard once this message has been received. This kind of keyboard can&#039;t be received in an incoming message; instead, updateChatReplyMarkup with messageId == 0 will be sent.
		 *
		 * @param isPersonal True, if the keyboard is removed only for the mentioned users or the target user of a reply.
		**/
		public ReplyMarkupRemoveKeyboard(boolean isPersonal) {
			this.isPersonal = isPersonal;
		}

		/**
		 * Instructs application to remove the keyboard once this message has been received. This kind of keyboard can&#039;t be received in an incoming message; instead, updateChatReplyMarkup with messageId == 0 will be sent.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ReplyMarkupRemoveKeyboard(DataInput input) throws IOException {
			this.isPersonal = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ReplyMarkupRemoveKeyboard.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ReplyMarkupRemoveKeyboard.CONSTRUCTOR);
			output.writeBoolean(this.isPersonal);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ReplyMarkupRemoveKeyboard replyMarkupRemoveKeyboard = (ReplyMarkupRemoveKeyboard) o;
			if (this.isPersonal != replyMarkupRemoveKeyboard.isPersonal) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Boolean.hashCode(this.isPersonal);
		}
	}

	/**
	 * Instructs application to force a reply to this message.
	**/
	public static final class ReplyMarkupForceReply extends ReplyMarkup {


		/**
		 * True, if a forced reply must automatically be shown to the current user. For outgoing messages, specify true to show the forced reply only for the mentioned users and for the target user of a reply.
		**/
		public boolean isPersonal;

		/**
		 * If non-empty, the placeholder to be shown in the input field when the reply is active; 0-64 characters.
		**/
		public String inputFieldPlaceholder;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1101461919;

		/**
		 * Instructs application to force a reply to this message.
		**/
		public ReplyMarkupForceReply() {}

		/**
		 * Instructs application to force a reply to this message.
		 *
		 * @param isPersonal True, if a forced reply must automatically be shown to the current user. For outgoing messages, specify true to show the forced reply only for the mentioned users and for the target user of a reply.
		 * @param inputFieldPlaceholder If non-empty, the placeholder to be shown in the input field when the reply is active; 0-64 characters.
		**/
		public ReplyMarkupForceReply(boolean isPersonal, String inputFieldPlaceholder) {
			this.isPersonal = isPersonal;
			this.inputFieldPlaceholder = inputFieldPlaceholder;
		}

		/**
		 * Instructs application to force a reply to this message.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ReplyMarkupForceReply(DataInput input) throws IOException {
			this.isPersonal = input.readBoolean();
			if (input.readBoolean()) {
				byte[] inputFieldPlaceholderTmp = new byte[input.readInt()];
				input.readFully(inputFieldPlaceholderTmp);
				this.inputFieldPlaceholder = new String(inputFieldPlaceholderTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ReplyMarkupForceReply.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ReplyMarkupForceReply.CONSTRUCTOR);
			output.writeBoolean(this.isPersonal);
			if (this.inputFieldPlaceholder == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] inputFieldPlaceholderTmp = this.inputFieldPlaceholder.getBytes(StandardCharsets.UTF_8);
				output.writeInt(inputFieldPlaceholderTmp.length);
				output.write(inputFieldPlaceholderTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ReplyMarkupForceReply replyMarkupForceReply = (ReplyMarkupForceReply) o;
			if (this.isPersonal != replyMarkupForceReply.isPersonal) {
				return false;
			}
			if (this.inputFieldPlaceholder != replyMarkupForceReply.inputFieldPlaceholder) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isPersonal);
			result = result * 31 + (this.inputFieldPlaceholder == null ? 0 : this.inputFieldPlaceholder.hashCode());
			return result;
		}
	}

	/**
	 * Contains a custom keyboard layout to quickly reply to bots.
	**/
	public static final class ReplyMarkupShowKeyboard extends ReplyMarkup {


		/**
		 * A list of rows of bot keyboard buttons.
		**/
		public KeyboardButton[][] rows;

		/**
		 * True, if the keyboard is supposed to always be shown when the ordinary keyboard is hidden.
		**/
		public boolean isPersistent;

		/**
		 * True, if the application needs to resize the keyboard vertically.
		**/
		public boolean resizeKeyboard;

		/**
		 * True, if the application needs to hide the keyboard after use.
		**/
		public boolean oneTime;

		/**
		 * True, if the keyboard must automatically be shown to the current user. For outgoing messages, specify true to show the keyboard only for the mentioned users and for the target user of a reply.
		**/
		public boolean isPersonal;

		/**
		 * If non-empty, the placeholder to be shown in the input field when the keyboard is active; 0-64 characters.
		**/
		public String inputFieldPlaceholder;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -791495984;

		/**
		 * Contains a custom keyboard layout to quickly reply to bots.
		**/
		public ReplyMarkupShowKeyboard() {}

		/**
		 * Contains a custom keyboard layout to quickly reply to bots.
		 *
		 * @param rows A list of rows of bot keyboard buttons.
		 * @param isPersistent True, if the keyboard is supposed to always be shown when the ordinary keyboard is hidden.
		 * @param resizeKeyboard True, if the application needs to resize the keyboard vertically.
		 * @param oneTime True, if the application needs to hide the keyboard after use.
		 * @param isPersonal True, if the keyboard must automatically be shown to the current user. For outgoing messages, specify true to show the keyboard only for the mentioned users and for the target user of a reply.
		 * @param inputFieldPlaceholder If non-empty, the placeholder to be shown in the input field when the keyboard is active; 0-64 characters.
		**/
		public ReplyMarkupShowKeyboard(KeyboardButton[][] rows,
				boolean isPersistent,
				boolean resizeKeyboard,
				boolean oneTime,
				boolean isPersonal,
				String inputFieldPlaceholder) {
			this.rows = rows;
			this.isPersistent = isPersistent;
			this.resizeKeyboard = resizeKeyboard;
			this.oneTime = oneTime;
			this.isPersonal = isPersonal;
			this.inputFieldPlaceholder = inputFieldPlaceholder;
		}

		/**
		 * Contains a custom keyboard layout to quickly reply to bots.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ReplyMarkupShowKeyboard(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.rows = new KeyboardButton[input.readInt()][];
				for (int i = 0; i < this.rows.length; i++) {
					this.rows[i] = new KeyboardButton[input.readInt()];					for (int j = 0; j < this.rows[i].length; j++) {
						if (KeyboardButton.CONSTRUCTOR != input.readInt()) {
							throw new UnsupportedOperationException();
						}
						this.rows[i][j] = new KeyboardButton(input);
					}
				}
			}
			this.isPersistent = input.readBoolean();
			this.resizeKeyboard = input.readBoolean();
			this.oneTime = input.readBoolean();
			this.isPersonal = input.readBoolean();
			if (input.readBoolean()) {
				byte[] inputFieldPlaceholderTmp = new byte[input.readInt()];
				input.readFully(inputFieldPlaceholderTmp);
				this.inputFieldPlaceholder = new String(inputFieldPlaceholderTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ReplyMarkupShowKeyboard.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ReplyMarkupShowKeyboard.CONSTRUCTOR);
			if (this.rows == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.rows.length);
				for (int i = 0; i < this.rows.length; i++) {
					output.writeInt(this.rows[i].length);
					for (int j = 0; j < this.rows[i].length; j++) {
						this.rows[i][j].serialize(output);
					}
				}
			}
			output.writeBoolean(this.isPersistent);
			output.writeBoolean(this.resizeKeyboard);
			output.writeBoolean(this.oneTime);
			output.writeBoolean(this.isPersonal);
			if (this.inputFieldPlaceholder == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] inputFieldPlaceholderTmp = this.inputFieldPlaceholder.getBytes(StandardCharsets.UTF_8);
				output.writeInt(inputFieldPlaceholderTmp.length);
				output.write(inputFieldPlaceholderTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ReplyMarkupShowKeyboard replyMarkupShowKeyboard = (ReplyMarkupShowKeyboard) o;
			if (!Arrays.deepEquals(this.rows, replyMarkupShowKeyboard.rows)) {
				return false;
			}
			if (this.isPersistent != replyMarkupShowKeyboard.isPersistent) {
				return false;
			}
			if (this.resizeKeyboard != replyMarkupShowKeyboard.resizeKeyboard) {
				return false;
			}
			if (this.oneTime != replyMarkupShowKeyboard.oneTime) {
				return false;
			}
			if (this.isPersonal != replyMarkupShowKeyboard.isPersonal) {
				return false;
			}
			if (this.inputFieldPlaceholder != replyMarkupShowKeyboard.inputFieldPlaceholder) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isPersistent);
			result = result * 31 + (Arrays.deepHashCode(this.rows));
			result = result * 31 + (this.inputFieldPlaceholder == null ? 0 : this.inputFieldPlaceholder.hashCode());
			return result;
		}
	}

	/**
	 * Contains an inline keyboard layout.
	**/
	public static final class ReplyMarkupInlineKeyboard extends ReplyMarkup {


		/**
		 * A list of rows of inline keyboard buttons.
		**/
		public InlineKeyboardButton[][] rows;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -619317658;

		/**
		 * Contains an inline keyboard layout.
		**/
		public ReplyMarkupInlineKeyboard() {}

		/**
		 * Contains an inline keyboard layout.
		 *
		 * @param rows A list of rows of inline keyboard buttons.
		**/
		public ReplyMarkupInlineKeyboard(InlineKeyboardButton[][] rows) {
			this.rows = rows;
		}

		/**
		 * Contains an inline keyboard layout.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ReplyMarkupInlineKeyboard(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.rows = new InlineKeyboardButton[input.readInt()][];
				for (int i = 0; i < this.rows.length; i++) {
					this.rows[i] = new InlineKeyboardButton[input.readInt()];					for (int j = 0; j < this.rows[i].length; j++) {
						if (InlineKeyboardButton.CONSTRUCTOR != input.readInt()) {
							throw new UnsupportedOperationException();
						}
						this.rows[i][j] = new InlineKeyboardButton(input);
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ReplyMarkupInlineKeyboard.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ReplyMarkupInlineKeyboard.CONSTRUCTOR);
			if (this.rows == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.rows.length);
				for (int i = 0; i < this.rows.length; i++) {
					output.writeInt(this.rows[i].length);
					for (int j = 0; j < this.rows[i].length; j++) {
						this.rows[i][j].serialize(output);
					}
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ReplyMarkupInlineKeyboard replyMarkupInlineKeyboard = (ReplyMarkupInlineKeyboard) o;
			if (!Arrays.deepEquals(this.rows, replyMarkupInlineKeyboard.rows)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.deepHashCode(this.rows);
		}
	}

	/**
	 * The password was reset.
	**/
	public static final class ResetPasswordResultOk extends ResetPasswordResult {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1397267463;

		/**
		 * The password was reset.
		**/
		public ResetPasswordResultOk() {}

		/**
		 * The password was reset.
		 *
		**/

		/**
		 * The password was reset.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ResetPasswordResultOk(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ResetPasswordResultOk.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ResetPasswordResultOk.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ResetPasswordResultOk.CONSTRUCTOR;
		}
	}

	/**
	 * The password reset request is pending.
	**/
	public static final class ResetPasswordResultPending extends ResetPasswordResult {


		/**
		 * Point in time (Unix timestamp) after which the password can be reset immediately using resetPassword.
		**/
		public int pendingResetDate;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1193925721;

		/**
		 * The password reset request is pending.
		**/
		public ResetPasswordResultPending() {}

		/**
		 * The password reset request is pending.
		 *
		 * @param pendingResetDate Point in time (Unix timestamp) after which the password can be reset immediately using resetPassword.
		**/
		public ResetPasswordResultPending(int pendingResetDate) {
			this.pendingResetDate = pendingResetDate;
		}

		/**
		 * The password reset request is pending.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ResetPasswordResultPending(DataInput input) throws IOException {
			this.pendingResetDate = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ResetPasswordResultPending.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ResetPasswordResultPending.CONSTRUCTOR);
			output.writeInt(this.pendingResetDate);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ResetPasswordResultPending resetPasswordResultPending = (ResetPasswordResultPending) o;
			if (this.pendingResetDate != resetPasswordResultPending.pendingResetDate) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.pendingResetDate);
		}
	}

	/**
	 * The password reset request was declined.
	**/
	public static final class ResetPasswordResultDeclined extends ResetPasswordResult {


		/**
		 * Point in time (Unix timestamp) when the password reset can be retried.
		**/
		public int retryDate;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1202200373;

		/**
		 * The password reset request was declined.
		**/
		public ResetPasswordResultDeclined() {}

		/**
		 * The password reset request was declined.
		 *
		 * @param retryDate Point in time (Unix timestamp) when the password reset can be retried.
		**/
		public ResetPasswordResultDeclined(int retryDate) {
			this.retryDate = retryDate;
		}

		/**
		 * The password reset request was declined.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ResetPasswordResultDeclined(DataInput input) throws IOException {
			this.retryDate = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ResetPasswordResultDeclined.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ResetPasswordResultDeclined.CONSTRUCTOR);
			output.writeInt(this.retryDate);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ResetPasswordResultDeclined resetPasswordResultDeclined = (ResetPasswordResultDeclined) o;
			if (this.retryDate != resetPasswordResultDeclined.retryDate) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.retryDate);
		}
	}

	/**
	 * A plain text.
	**/
	public static final class RichTextPlain extends RichText {


		/**
		 * Text.
		**/
		public String text;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 482617702;

		/**
		 * A plain text.
		**/
		public RichTextPlain() {}

		/**
		 * A plain text.
		 *
		 * @param text Text.
		**/
		public RichTextPlain(String text) {
			this.text = text;
		}

		/**
		 * A plain text.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RichTextPlain(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] textTmp = new byte[input.readInt()];
				input.readFully(textTmp);
				this.text = new String(textTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RichTextPlain.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RichTextPlain.CONSTRUCTOR);
			if (this.text == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] textTmp = this.text.getBytes(StandardCharsets.UTF_8);
				output.writeInt(textTmp.length);
				output.write(textTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			RichTextPlain richTextPlain = (RichTextPlain) o;
			if (this.text != richTextPlain.text) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.text == null ? 0 : this.text.hashCode();
		}
	}

	/**
	 * A bold rich text.
	**/
	public static final class RichTextBold extends RichText {


		/**
		 * Text.
		**/
		public RichText text;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1670844268;

		/**
		 * A bold rich text.
		**/
		public RichTextBold() {}

		/**
		 * A bold rich text.
		 *
		 * @param text Text.
		**/
		public RichTextBold(RichText text) {
			this.text = text;
		}

		/**
		 * A bold rich text.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RichTextBold(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case RichTextPlain.CONSTRUCTOR: this.text = new RichTextPlain(input); break;
					case RichTextBold.CONSTRUCTOR: this.text = new RichTextBold(input); break;
					case RichTextItalic.CONSTRUCTOR: this.text = new RichTextItalic(input); break;
					case RichTextUnderline.CONSTRUCTOR: this.text = new RichTextUnderline(input); break;
					case RichTextStrikethrough.CONSTRUCTOR: this.text = new RichTextStrikethrough(input); break;
					case RichTextFixed.CONSTRUCTOR: this.text = new RichTextFixed(input); break;
					case RichTextUrl.CONSTRUCTOR: this.text = new RichTextUrl(input); break;
					case RichTextEmailAddress.CONSTRUCTOR: this.text = new RichTextEmailAddress(input); break;
					case RichTextSubscript.CONSTRUCTOR: this.text = new RichTextSubscript(input); break;
					case RichTextSuperscript.CONSTRUCTOR: this.text = new RichTextSuperscript(input); break;
					case RichTextMarked.CONSTRUCTOR: this.text = new RichTextMarked(input); break;
					case RichTextPhoneNumber.CONSTRUCTOR: this.text = new RichTextPhoneNumber(input); break;
					case RichTextIcon.CONSTRUCTOR: this.text = new RichTextIcon(input); break;
					case RichTextReference.CONSTRUCTOR: this.text = new RichTextReference(input); break;
					case RichTextAnchor.CONSTRUCTOR: this.text = new RichTextAnchor(input); break;
					case RichTextAnchorLink.CONSTRUCTOR: this.text = new RichTextAnchorLink(input); break;
					case RichTexts.CONSTRUCTOR: this.text = new RichTexts(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RichTextBold.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RichTextBold.CONSTRUCTOR);
			if (this.text == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.text.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			RichTextBold richTextBold = (RichTextBold) o;
			if (!Objects.equals(this.text, richTextBold.text)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.text == null ? 0 : this.text.hashCode();
		}
	}

	/**
	 * An italicized rich text.
	**/
	public static final class RichTextItalic extends RichText {


		/**
		 * Text.
		**/
		public RichText text;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1853354047;

		/**
		 * An italicized rich text.
		**/
		public RichTextItalic() {}

		/**
		 * An italicized rich text.
		 *
		 * @param text Text.
		**/
		public RichTextItalic(RichText text) {
			this.text = text;
		}

		/**
		 * An italicized rich text.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RichTextItalic(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case RichTextPlain.CONSTRUCTOR: this.text = new RichTextPlain(input); break;
					case RichTextBold.CONSTRUCTOR: this.text = new RichTextBold(input); break;
					case RichTextItalic.CONSTRUCTOR: this.text = new RichTextItalic(input); break;
					case RichTextUnderline.CONSTRUCTOR: this.text = new RichTextUnderline(input); break;
					case RichTextStrikethrough.CONSTRUCTOR: this.text = new RichTextStrikethrough(input); break;
					case RichTextFixed.CONSTRUCTOR: this.text = new RichTextFixed(input); break;
					case RichTextUrl.CONSTRUCTOR: this.text = new RichTextUrl(input); break;
					case RichTextEmailAddress.CONSTRUCTOR: this.text = new RichTextEmailAddress(input); break;
					case RichTextSubscript.CONSTRUCTOR: this.text = new RichTextSubscript(input); break;
					case RichTextSuperscript.CONSTRUCTOR: this.text = new RichTextSuperscript(input); break;
					case RichTextMarked.CONSTRUCTOR: this.text = new RichTextMarked(input); break;
					case RichTextPhoneNumber.CONSTRUCTOR: this.text = new RichTextPhoneNumber(input); break;
					case RichTextIcon.CONSTRUCTOR: this.text = new RichTextIcon(input); break;
					case RichTextReference.CONSTRUCTOR: this.text = new RichTextReference(input); break;
					case RichTextAnchor.CONSTRUCTOR: this.text = new RichTextAnchor(input); break;
					case RichTextAnchorLink.CONSTRUCTOR: this.text = new RichTextAnchorLink(input); break;
					case RichTexts.CONSTRUCTOR: this.text = new RichTexts(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RichTextItalic.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RichTextItalic.CONSTRUCTOR);
			if (this.text == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.text.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			RichTextItalic richTextItalic = (RichTextItalic) o;
			if (!Objects.equals(this.text, richTextItalic.text)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.text == null ? 0 : this.text.hashCode();
		}
	}

	/**
	 * An underlined rich text.
	**/
	public static final class RichTextUnderline extends RichText {


		/**
		 * Text.
		**/
		public RichText text;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -536019572;

		/**
		 * An underlined rich text.
		**/
		public RichTextUnderline() {}

		/**
		 * An underlined rich text.
		 *
		 * @param text Text.
		**/
		public RichTextUnderline(RichText text) {
			this.text = text;
		}

		/**
		 * An underlined rich text.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RichTextUnderline(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case RichTextPlain.CONSTRUCTOR: this.text = new RichTextPlain(input); break;
					case RichTextBold.CONSTRUCTOR: this.text = new RichTextBold(input); break;
					case RichTextItalic.CONSTRUCTOR: this.text = new RichTextItalic(input); break;
					case RichTextUnderline.CONSTRUCTOR: this.text = new RichTextUnderline(input); break;
					case RichTextStrikethrough.CONSTRUCTOR: this.text = new RichTextStrikethrough(input); break;
					case RichTextFixed.CONSTRUCTOR: this.text = new RichTextFixed(input); break;
					case RichTextUrl.CONSTRUCTOR: this.text = new RichTextUrl(input); break;
					case RichTextEmailAddress.CONSTRUCTOR: this.text = new RichTextEmailAddress(input); break;
					case RichTextSubscript.CONSTRUCTOR: this.text = new RichTextSubscript(input); break;
					case RichTextSuperscript.CONSTRUCTOR: this.text = new RichTextSuperscript(input); break;
					case RichTextMarked.CONSTRUCTOR: this.text = new RichTextMarked(input); break;
					case RichTextPhoneNumber.CONSTRUCTOR: this.text = new RichTextPhoneNumber(input); break;
					case RichTextIcon.CONSTRUCTOR: this.text = new RichTextIcon(input); break;
					case RichTextReference.CONSTRUCTOR: this.text = new RichTextReference(input); break;
					case RichTextAnchor.CONSTRUCTOR: this.text = new RichTextAnchor(input); break;
					case RichTextAnchorLink.CONSTRUCTOR: this.text = new RichTextAnchorLink(input); break;
					case RichTexts.CONSTRUCTOR: this.text = new RichTexts(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RichTextUnderline.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RichTextUnderline.CONSTRUCTOR);
			if (this.text == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.text.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			RichTextUnderline richTextUnderline = (RichTextUnderline) o;
			if (!Objects.equals(this.text, richTextUnderline.text)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.text == null ? 0 : this.text.hashCode();
		}
	}

	/**
	 * A strikethrough rich text.
	**/
	public static final class RichTextStrikethrough extends RichText {


		/**
		 * Text.
		**/
		public RichText text;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 723413585;

		/**
		 * A strikethrough rich text.
		**/
		public RichTextStrikethrough() {}

		/**
		 * A strikethrough rich text.
		 *
		 * @param text Text.
		**/
		public RichTextStrikethrough(RichText text) {
			this.text = text;
		}

		/**
		 * A strikethrough rich text.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RichTextStrikethrough(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case RichTextPlain.CONSTRUCTOR: this.text = new RichTextPlain(input); break;
					case RichTextBold.CONSTRUCTOR: this.text = new RichTextBold(input); break;
					case RichTextItalic.CONSTRUCTOR: this.text = new RichTextItalic(input); break;
					case RichTextUnderline.CONSTRUCTOR: this.text = new RichTextUnderline(input); break;
					case RichTextStrikethrough.CONSTRUCTOR: this.text = new RichTextStrikethrough(input); break;
					case RichTextFixed.CONSTRUCTOR: this.text = new RichTextFixed(input); break;
					case RichTextUrl.CONSTRUCTOR: this.text = new RichTextUrl(input); break;
					case RichTextEmailAddress.CONSTRUCTOR: this.text = new RichTextEmailAddress(input); break;
					case RichTextSubscript.CONSTRUCTOR: this.text = new RichTextSubscript(input); break;
					case RichTextSuperscript.CONSTRUCTOR: this.text = new RichTextSuperscript(input); break;
					case RichTextMarked.CONSTRUCTOR: this.text = new RichTextMarked(input); break;
					case RichTextPhoneNumber.CONSTRUCTOR: this.text = new RichTextPhoneNumber(input); break;
					case RichTextIcon.CONSTRUCTOR: this.text = new RichTextIcon(input); break;
					case RichTextReference.CONSTRUCTOR: this.text = new RichTextReference(input); break;
					case RichTextAnchor.CONSTRUCTOR: this.text = new RichTextAnchor(input); break;
					case RichTextAnchorLink.CONSTRUCTOR: this.text = new RichTextAnchorLink(input); break;
					case RichTexts.CONSTRUCTOR: this.text = new RichTexts(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RichTextStrikethrough.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RichTextStrikethrough.CONSTRUCTOR);
			if (this.text == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.text.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			RichTextStrikethrough richTextStrikethrough = (RichTextStrikethrough) o;
			if (!Objects.equals(this.text, richTextStrikethrough.text)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.text == null ? 0 : this.text.hashCode();
		}
	}

	/**
	 * A fixed-width rich text.
	**/
	public static final class RichTextFixed extends RichText {


		/**
		 * Text.
		**/
		public RichText text;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1271496249;

		/**
		 * A fixed-width rich text.
		**/
		public RichTextFixed() {}

		/**
		 * A fixed-width rich text.
		 *
		 * @param text Text.
		**/
		public RichTextFixed(RichText text) {
			this.text = text;
		}

		/**
		 * A fixed-width rich text.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RichTextFixed(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case RichTextPlain.CONSTRUCTOR: this.text = new RichTextPlain(input); break;
					case RichTextBold.CONSTRUCTOR: this.text = new RichTextBold(input); break;
					case RichTextItalic.CONSTRUCTOR: this.text = new RichTextItalic(input); break;
					case RichTextUnderline.CONSTRUCTOR: this.text = new RichTextUnderline(input); break;
					case RichTextStrikethrough.CONSTRUCTOR: this.text = new RichTextStrikethrough(input); break;
					case RichTextFixed.CONSTRUCTOR: this.text = new RichTextFixed(input); break;
					case RichTextUrl.CONSTRUCTOR: this.text = new RichTextUrl(input); break;
					case RichTextEmailAddress.CONSTRUCTOR: this.text = new RichTextEmailAddress(input); break;
					case RichTextSubscript.CONSTRUCTOR: this.text = new RichTextSubscript(input); break;
					case RichTextSuperscript.CONSTRUCTOR: this.text = new RichTextSuperscript(input); break;
					case RichTextMarked.CONSTRUCTOR: this.text = new RichTextMarked(input); break;
					case RichTextPhoneNumber.CONSTRUCTOR: this.text = new RichTextPhoneNumber(input); break;
					case RichTextIcon.CONSTRUCTOR: this.text = new RichTextIcon(input); break;
					case RichTextReference.CONSTRUCTOR: this.text = new RichTextReference(input); break;
					case RichTextAnchor.CONSTRUCTOR: this.text = new RichTextAnchor(input); break;
					case RichTextAnchorLink.CONSTRUCTOR: this.text = new RichTextAnchorLink(input); break;
					case RichTexts.CONSTRUCTOR: this.text = new RichTexts(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RichTextFixed.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RichTextFixed.CONSTRUCTOR);
			if (this.text == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.text.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			RichTextFixed richTextFixed = (RichTextFixed) o;
			if (!Objects.equals(this.text, richTextFixed.text)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.text == null ? 0 : this.text.hashCode();
		}
	}

	/**
	 * A rich text URL link.
	**/
	public static final class RichTextUrl extends RichText {


		/**
		 * Text.
		**/
		public RichText text;

		/**
		 * URL.
		**/
		public String url;

		/**
		 * True, if the URL has cached instant view server-side.
		**/
		public boolean isCached;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 83939092;

		/**
		 * A rich text URL link.
		**/
		public RichTextUrl() {}

		/**
		 * A rich text URL link.
		 *
		 * @param text Text.
		 * @param url URL.
		 * @param isCached True, if the URL has cached instant view server-side.
		**/
		public RichTextUrl(RichText text, String url, boolean isCached) {
			this.text = text;
			this.url = url;
			this.isCached = isCached;
		}

		/**
		 * A rich text URL link.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RichTextUrl(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case RichTextPlain.CONSTRUCTOR: this.text = new RichTextPlain(input); break;
					case RichTextBold.CONSTRUCTOR: this.text = new RichTextBold(input); break;
					case RichTextItalic.CONSTRUCTOR: this.text = new RichTextItalic(input); break;
					case RichTextUnderline.CONSTRUCTOR: this.text = new RichTextUnderline(input); break;
					case RichTextStrikethrough.CONSTRUCTOR: this.text = new RichTextStrikethrough(input); break;
					case RichTextFixed.CONSTRUCTOR: this.text = new RichTextFixed(input); break;
					case RichTextUrl.CONSTRUCTOR: this.text = new RichTextUrl(input); break;
					case RichTextEmailAddress.CONSTRUCTOR: this.text = new RichTextEmailAddress(input); break;
					case RichTextSubscript.CONSTRUCTOR: this.text = new RichTextSubscript(input); break;
					case RichTextSuperscript.CONSTRUCTOR: this.text = new RichTextSuperscript(input); break;
					case RichTextMarked.CONSTRUCTOR: this.text = new RichTextMarked(input); break;
					case RichTextPhoneNumber.CONSTRUCTOR: this.text = new RichTextPhoneNumber(input); break;
					case RichTextIcon.CONSTRUCTOR: this.text = new RichTextIcon(input); break;
					case RichTextReference.CONSTRUCTOR: this.text = new RichTextReference(input); break;
					case RichTextAnchor.CONSTRUCTOR: this.text = new RichTextAnchor(input); break;
					case RichTextAnchorLink.CONSTRUCTOR: this.text = new RichTextAnchorLink(input); break;
					case RichTexts.CONSTRUCTOR: this.text = new RichTexts(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				byte[] urlTmp = new byte[input.readInt()];
				input.readFully(urlTmp);
				this.url = new String(urlTmp, StandardCharsets.UTF_8);
			}
			this.isCached = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RichTextUrl.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RichTextUrl.CONSTRUCTOR);
			if (this.text == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.text.serialize(output);
			}
			if (this.url == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] urlTmp = this.url.getBytes(StandardCharsets.UTF_8);
				output.writeInt(urlTmp.length);
				output.write(urlTmp);
			}
			output.writeBoolean(this.isCached);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			RichTextUrl richTextUrl = (RichTextUrl) o;
			if (!Objects.equals(this.text, richTextUrl.text)) {
				return false;
			}
			if (this.url != richTextUrl.url) {
				return false;
			}
			if (this.isCached != richTextUrl.isCached) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isCached);
			result = result * 31 + (this.text == null ? 0 : this.text.hashCode());
			result = result * 31 + (this.url == null ? 0 : this.url.hashCode());
			return result;
		}
	}

	/**
	 * A rich text email link.
	**/
	public static final class RichTextEmailAddress extends RichText {


		/**
		 * Text.
		**/
		public RichText text;

		/**
		 * Email address.
		**/
		public String emailAddress;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 40018679;

		/**
		 * A rich text email link.
		**/
		public RichTextEmailAddress() {}

		/**
		 * A rich text email link.
		 *
		 * @param text Text.
		 * @param emailAddress Email address.
		**/
		public RichTextEmailAddress(RichText text, String emailAddress) {
			this.text = text;
			this.emailAddress = emailAddress;
		}

		/**
		 * A rich text email link.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RichTextEmailAddress(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case RichTextPlain.CONSTRUCTOR: this.text = new RichTextPlain(input); break;
					case RichTextBold.CONSTRUCTOR: this.text = new RichTextBold(input); break;
					case RichTextItalic.CONSTRUCTOR: this.text = new RichTextItalic(input); break;
					case RichTextUnderline.CONSTRUCTOR: this.text = new RichTextUnderline(input); break;
					case RichTextStrikethrough.CONSTRUCTOR: this.text = new RichTextStrikethrough(input); break;
					case RichTextFixed.CONSTRUCTOR: this.text = new RichTextFixed(input); break;
					case RichTextUrl.CONSTRUCTOR: this.text = new RichTextUrl(input); break;
					case RichTextEmailAddress.CONSTRUCTOR: this.text = new RichTextEmailAddress(input); break;
					case RichTextSubscript.CONSTRUCTOR: this.text = new RichTextSubscript(input); break;
					case RichTextSuperscript.CONSTRUCTOR: this.text = new RichTextSuperscript(input); break;
					case RichTextMarked.CONSTRUCTOR: this.text = new RichTextMarked(input); break;
					case RichTextPhoneNumber.CONSTRUCTOR: this.text = new RichTextPhoneNumber(input); break;
					case RichTextIcon.CONSTRUCTOR: this.text = new RichTextIcon(input); break;
					case RichTextReference.CONSTRUCTOR: this.text = new RichTextReference(input); break;
					case RichTextAnchor.CONSTRUCTOR: this.text = new RichTextAnchor(input); break;
					case RichTextAnchorLink.CONSTRUCTOR: this.text = new RichTextAnchorLink(input); break;
					case RichTexts.CONSTRUCTOR: this.text = new RichTexts(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				byte[] emailAddressTmp = new byte[input.readInt()];
				input.readFully(emailAddressTmp);
				this.emailAddress = new String(emailAddressTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RichTextEmailAddress.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RichTextEmailAddress.CONSTRUCTOR);
			if (this.text == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.text.serialize(output);
			}
			if (this.emailAddress == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] emailAddressTmp = this.emailAddress.getBytes(StandardCharsets.UTF_8);
				output.writeInt(emailAddressTmp.length);
				output.write(emailAddressTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			RichTextEmailAddress richTextEmailAddress = (RichTextEmailAddress) o;
			if (!Objects.equals(this.text, richTextEmailAddress.text)) {
				return false;
			}
			if (this.emailAddress != richTextEmailAddress.emailAddress) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.text == null ? 0 : this.text.hashCode();
			result = result * 31 + (this.emailAddress == null ? 0 : this.emailAddress.hashCode());
			return result;
		}
	}

	/**
	 * A subscript rich text.
	**/
	public static final class RichTextSubscript extends RichText {


		/**
		 * Text.
		**/
		public RichText text;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -868197812;

		/**
		 * A subscript rich text.
		**/
		public RichTextSubscript() {}

		/**
		 * A subscript rich text.
		 *
		 * @param text Text.
		**/
		public RichTextSubscript(RichText text) {
			this.text = text;
		}

		/**
		 * A subscript rich text.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RichTextSubscript(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case RichTextPlain.CONSTRUCTOR: this.text = new RichTextPlain(input); break;
					case RichTextBold.CONSTRUCTOR: this.text = new RichTextBold(input); break;
					case RichTextItalic.CONSTRUCTOR: this.text = new RichTextItalic(input); break;
					case RichTextUnderline.CONSTRUCTOR: this.text = new RichTextUnderline(input); break;
					case RichTextStrikethrough.CONSTRUCTOR: this.text = new RichTextStrikethrough(input); break;
					case RichTextFixed.CONSTRUCTOR: this.text = new RichTextFixed(input); break;
					case RichTextUrl.CONSTRUCTOR: this.text = new RichTextUrl(input); break;
					case RichTextEmailAddress.CONSTRUCTOR: this.text = new RichTextEmailAddress(input); break;
					case RichTextSubscript.CONSTRUCTOR: this.text = new RichTextSubscript(input); break;
					case RichTextSuperscript.CONSTRUCTOR: this.text = new RichTextSuperscript(input); break;
					case RichTextMarked.CONSTRUCTOR: this.text = new RichTextMarked(input); break;
					case RichTextPhoneNumber.CONSTRUCTOR: this.text = new RichTextPhoneNumber(input); break;
					case RichTextIcon.CONSTRUCTOR: this.text = new RichTextIcon(input); break;
					case RichTextReference.CONSTRUCTOR: this.text = new RichTextReference(input); break;
					case RichTextAnchor.CONSTRUCTOR: this.text = new RichTextAnchor(input); break;
					case RichTextAnchorLink.CONSTRUCTOR: this.text = new RichTextAnchorLink(input); break;
					case RichTexts.CONSTRUCTOR: this.text = new RichTexts(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RichTextSubscript.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RichTextSubscript.CONSTRUCTOR);
			if (this.text == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.text.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			RichTextSubscript richTextSubscript = (RichTextSubscript) o;
			if (!Objects.equals(this.text, richTextSubscript.text)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.text == null ? 0 : this.text.hashCode();
		}
	}

	/**
	 * A superscript rich text.
	**/
	public static final class RichTextSuperscript extends RichText {


		/**
		 * Text.
		**/
		public RichText text;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -382241437;

		/**
		 * A superscript rich text.
		**/
		public RichTextSuperscript() {}

		/**
		 * A superscript rich text.
		 *
		 * @param text Text.
		**/
		public RichTextSuperscript(RichText text) {
			this.text = text;
		}

		/**
		 * A superscript rich text.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RichTextSuperscript(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case RichTextPlain.CONSTRUCTOR: this.text = new RichTextPlain(input); break;
					case RichTextBold.CONSTRUCTOR: this.text = new RichTextBold(input); break;
					case RichTextItalic.CONSTRUCTOR: this.text = new RichTextItalic(input); break;
					case RichTextUnderline.CONSTRUCTOR: this.text = new RichTextUnderline(input); break;
					case RichTextStrikethrough.CONSTRUCTOR: this.text = new RichTextStrikethrough(input); break;
					case RichTextFixed.CONSTRUCTOR: this.text = new RichTextFixed(input); break;
					case RichTextUrl.CONSTRUCTOR: this.text = new RichTextUrl(input); break;
					case RichTextEmailAddress.CONSTRUCTOR: this.text = new RichTextEmailAddress(input); break;
					case RichTextSubscript.CONSTRUCTOR: this.text = new RichTextSubscript(input); break;
					case RichTextSuperscript.CONSTRUCTOR: this.text = new RichTextSuperscript(input); break;
					case RichTextMarked.CONSTRUCTOR: this.text = new RichTextMarked(input); break;
					case RichTextPhoneNumber.CONSTRUCTOR: this.text = new RichTextPhoneNumber(input); break;
					case RichTextIcon.CONSTRUCTOR: this.text = new RichTextIcon(input); break;
					case RichTextReference.CONSTRUCTOR: this.text = new RichTextReference(input); break;
					case RichTextAnchor.CONSTRUCTOR: this.text = new RichTextAnchor(input); break;
					case RichTextAnchorLink.CONSTRUCTOR: this.text = new RichTextAnchorLink(input); break;
					case RichTexts.CONSTRUCTOR: this.text = new RichTexts(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RichTextSuperscript.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RichTextSuperscript.CONSTRUCTOR);
			if (this.text == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.text.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			RichTextSuperscript richTextSuperscript = (RichTextSuperscript) o;
			if (!Objects.equals(this.text, richTextSuperscript.text)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.text == null ? 0 : this.text.hashCode();
		}
	}

	/**
	 * A marked rich text.
	**/
	public static final class RichTextMarked extends RichText {


		/**
		 * Text.
		**/
		public RichText text;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1271999614;

		/**
		 * A marked rich text.
		**/
		public RichTextMarked() {}

		/**
		 * A marked rich text.
		 *
		 * @param text Text.
		**/
		public RichTextMarked(RichText text) {
			this.text = text;
		}

		/**
		 * A marked rich text.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RichTextMarked(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case RichTextPlain.CONSTRUCTOR: this.text = new RichTextPlain(input); break;
					case RichTextBold.CONSTRUCTOR: this.text = new RichTextBold(input); break;
					case RichTextItalic.CONSTRUCTOR: this.text = new RichTextItalic(input); break;
					case RichTextUnderline.CONSTRUCTOR: this.text = new RichTextUnderline(input); break;
					case RichTextStrikethrough.CONSTRUCTOR: this.text = new RichTextStrikethrough(input); break;
					case RichTextFixed.CONSTRUCTOR: this.text = new RichTextFixed(input); break;
					case RichTextUrl.CONSTRUCTOR: this.text = new RichTextUrl(input); break;
					case RichTextEmailAddress.CONSTRUCTOR: this.text = new RichTextEmailAddress(input); break;
					case RichTextSubscript.CONSTRUCTOR: this.text = new RichTextSubscript(input); break;
					case RichTextSuperscript.CONSTRUCTOR: this.text = new RichTextSuperscript(input); break;
					case RichTextMarked.CONSTRUCTOR: this.text = new RichTextMarked(input); break;
					case RichTextPhoneNumber.CONSTRUCTOR: this.text = new RichTextPhoneNumber(input); break;
					case RichTextIcon.CONSTRUCTOR: this.text = new RichTextIcon(input); break;
					case RichTextReference.CONSTRUCTOR: this.text = new RichTextReference(input); break;
					case RichTextAnchor.CONSTRUCTOR: this.text = new RichTextAnchor(input); break;
					case RichTextAnchorLink.CONSTRUCTOR: this.text = new RichTextAnchorLink(input); break;
					case RichTexts.CONSTRUCTOR: this.text = new RichTexts(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RichTextMarked.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RichTextMarked.CONSTRUCTOR);
			if (this.text == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.text.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			RichTextMarked richTextMarked = (RichTextMarked) o;
			if (!Objects.equals(this.text, richTextMarked.text)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.text == null ? 0 : this.text.hashCode();
		}
	}

	/**
	 * A rich text phone number.
	**/
	public static final class RichTextPhoneNumber extends RichText {


		/**
		 * Text.
		**/
		public RichText text;

		/**
		 * Phone number.
		**/
		public String phoneNumber;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 128521539;

		/**
		 * A rich text phone number.
		**/
		public RichTextPhoneNumber() {}

		/**
		 * A rich text phone number.
		 *
		 * @param text Text.
		 * @param phoneNumber Phone number.
		**/
		public RichTextPhoneNumber(RichText text, String phoneNumber) {
			this.text = text;
			this.phoneNumber = phoneNumber;
		}

		/**
		 * A rich text phone number.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RichTextPhoneNumber(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case RichTextPlain.CONSTRUCTOR: this.text = new RichTextPlain(input); break;
					case RichTextBold.CONSTRUCTOR: this.text = new RichTextBold(input); break;
					case RichTextItalic.CONSTRUCTOR: this.text = new RichTextItalic(input); break;
					case RichTextUnderline.CONSTRUCTOR: this.text = new RichTextUnderline(input); break;
					case RichTextStrikethrough.CONSTRUCTOR: this.text = new RichTextStrikethrough(input); break;
					case RichTextFixed.CONSTRUCTOR: this.text = new RichTextFixed(input); break;
					case RichTextUrl.CONSTRUCTOR: this.text = new RichTextUrl(input); break;
					case RichTextEmailAddress.CONSTRUCTOR: this.text = new RichTextEmailAddress(input); break;
					case RichTextSubscript.CONSTRUCTOR: this.text = new RichTextSubscript(input); break;
					case RichTextSuperscript.CONSTRUCTOR: this.text = new RichTextSuperscript(input); break;
					case RichTextMarked.CONSTRUCTOR: this.text = new RichTextMarked(input); break;
					case RichTextPhoneNumber.CONSTRUCTOR: this.text = new RichTextPhoneNumber(input); break;
					case RichTextIcon.CONSTRUCTOR: this.text = new RichTextIcon(input); break;
					case RichTextReference.CONSTRUCTOR: this.text = new RichTextReference(input); break;
					case RichTextAnchor.CONSTRUCTOR: this.text = new RichTextAnchor(input); break;
					case RichTextAnchorLink.CONSTRUCTOR: this.text = new RichTextAnchorLink(input); break;
					case RichTexts.CONSTRUCTOR: this.text = new RichTexts(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				byte[] phoneNumberTmp = new byte[input.readInt()];
				input.readFully(phoneNumberTmp);
				this.phoneNumber = new String(phoneNumberTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RichTextPhoneNumber.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RichTextPhoneNumber.CONSTRUCTOR);
			if (this.text == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.text.serialize(output);
			}
			if (this.phoneNumber == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] phoneNumberTmp = this.phoneNumber.getBytes(StandardCharsets.UTF_8);
				output.writeInt(phoneNumberTmp.length);
				output.write(phoneNumberTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			RichTextPhoneNumber richTextPhoneNumber = (RichTextPhoneNumber) o;
			if (!Objects.equals(this.text, richTextPhoneNumber.text)) {
				return false;
			}
			if (this.phoneNumber != richTextPhoneNumber.phoneNumber) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.text == null ? 0 : this.text.hashCode();
			result = result * 31 + (this.phoneNumber == null ? 0 : this.phoneNumber.hashCode());
			return result;
		}
	}

	/**
	 * A small image inside the text.
	**/
	public static final class RichTextIcon extends RichText {


		/**
		 * The image represented as a document. The image can be in GIF, JPEG or PNG format.
		**/
		public Document document;

		/**
		 * Width of a bounding box in which the image must be shown; 0 if unknown.
		**/
		public int width;

		/**
		 * Height of a bounding box in which the image must be shown; 0 if unknown.
		**/
		public int height;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1480316158;

		/**
		 * A small image inside the text.
		**/
		public RichTextIcon() {}

		/**
		 * A small image inside the text.
		 *
		 * @param document The image represented as a document. The image can be in GIF, JPEG or PNG format.
		 * @param width Width of a bounding box in which the image must be shown; 0 if unknown.
		 * @param height Height of a bounding box in which the image must be shown; 0 if unknown.
		**/
		public RichTextIcon(Document document, int width, int height) {
			this.document = document;
			this.width = width;
			this.height = height;
		}

		/**
		 * A small image inside the text.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RichTextIcon(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Document.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.document = new Document(input);
			}
			this.width = input.readInt();
			this.height = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RichTextIcon.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RichTextIcon.CONSTRUCTOR);
			if (this.document == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.document.serialize(output);
			}
			output.writeInt(this.width);
			output.writeInt(this.height);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			RichTextIcon richTextIcon = (RichTextIcon) o;
			if (!Objects.equals(this.document, richTextIcon.document)) {
				return false;
			}
			if (this.width != richTextIcon.width) {
				return false;
			}
			if (this.height != richTextIcon.height) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.width);
			result = result * 31 + (this.document == null ? 0 : this.document.hashCode());
			return result;
		}
	}

	/**
	 * A reference to a richTexts object on the same web page.
	**/
	public static final class RichTextReference extends RichText {


		/**
		 * The text.
		**/
		public RichText text;

		/**
		 * The name of a richTextAnchor object, which is the first element of the target richTexts object.
		**/
		public String anchorName;

		/**
		 * An HTTP URL, opening the reference.
		**/
		public String url;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1147530634;

		/**
		 * A reference to a richTexts object on the same web page.
		**/
		public RichTextReference() {}

		/**
		 * A reference to a richTexts object on the same web page.
		 *
		 * @param text The text.
		 * @param anchorName The name of a richTextAnchor object, which is the first element of the target richTexts object.
		 * @param url An HTTP URL, opening the reference.
		**/
		public RichTextReference(RichText text, String anchorName, String url) {
			this.text = text;
			this.anchorName = anchorName;
			this.url = url;
		}

		/**
		 * A reference to a richTexts object on the same web page.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RichTextReference(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case RichTextPlain.CONSTRUCTOR: this.text = new RichTextPlain(input); break;
					case RichTextBold.CONSTRUCTOR: this.text = new RichTextBold(input); break;
					case RichTextItalic.CONSTRUCTOR: this.text = new RichTextItalic(input); break;
					case RichTextUnderline.CONSTRUCTOR: this.text = new RichTextUnderline(input); break;
					case RichTextStrikethrough.CONSTRUCTOR: this.text = new RichTextStrikethrough(input); break;
					case RichTextFixed.CONSTRUCTOR: this.text = new RichTextFixed(input); break;
					case RichTextUrl.CONSTRUCTOR: this.text = new RichTextUrl(input); break;
					case RichTextEmailAddress.CONSTRUCTOR: this.text = new RichTextEmailAddress(input); break;
					case RichTextSubscript.CONSTRUCTOR: this.text = new RichTextSubscript(input); break;
					case RichTextSuperscript.CONSTRUCTOR: this.text = new RichTextSuperscript(input); break;
					case RichTextMarked.CONSTRUCTOR: this.text = new RichTextMarked(input); break;
					case RichTextPhoneNumber.CONSTRUCTOR: this.text = new RichTextPhoneNumber(input); break;
					case RichTextIcon.CONSTRUCTOR: this.text = new RichTextIcon(input); break;
					case RichTextReference.CONSTRUCTOR: this.text = new RichTextReference(input); break;
					case RichTextAnchor.CONSTRUCTOR: this.text = new RichTextAnchor(input); break;
					case RichTextAnchorLink.CONSTRUCTOR: this.text = new RichTextAnchorLink(input); break;
					case RichTexts.CONSTRUCTOR: this.text = new RichTexts(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				byte[] anchorNameTmp = new byte[input.readInt()];
				input.readFully(anchorNameTmp);
				this.anchorName = new String(anchorNameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] urlTmp = new byte[input.readInt()];
				input.readFully(urlTmp);
				this.url = new String(urlTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RichTextReference.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RichTextReference.CONSTRUCTOR);
			if (this.text == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.text.serialize(output);
			}
			if (this.anchorName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] anchorNameTmp = this.anchorName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(anchorNameTmp.length);
				output.write(anchorNameTmp);
			}
			if (this.url == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] urlTmp = this.url.getBytes(StandardCharsets.UTF_8);
				output.writeInt(urlTmp.length);
				output.write(urlTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			RichTextReference richTextReference = (RichTextReference) o;
			if (!Objects.equals(this.text, richTextReference.text)) {
				return false;
			}
			if (this.anchorName != richTextReference.anchorName) {
				return false;
			}
			if (this.url != richTextReference.url) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.text == null ? 0 : this.text.hashCode();
			result = result * 31 + (this.anchorName == null ? 0 : this.anchorName.hashCode());
			result = result * 31 + (this.url == null ? 0 : this.url.hashCode());
			return result;
		}
	}

	/**
	 * An anchor.
	**/
	public static final class RichTextAnchor extends RichText {


		/**
		 * Anchor name.
		**/
		public String name;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1316950068;

		/**
		 * An anchor.
		**/
		public RichTextAnchor() {}

		/**
		 * An anchor.
		 *
		 * @param name Anchor name.
		**/
		public RichTextAnchor(String name) {
			this.name = name;
		}

		/**
		 * An anchor.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RichTextAnchor(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] nameTmp = new byte[input.readInt()];
				input.readFully(nameTmp);
				this.name = new String(nameTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RichTextAnchor.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RichTextAnchor.CONSTRUCTOR);
			if (this.name == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nameTmp = this.name.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nameTmp.length);
				output.write(nameTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			RichTextAnchor richTextAnchor = (RichTextAnchor) o;
			if (this.name != richTextAnchor.name) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.name == null ? 0 : this.name.hashCode();
		}
	}

	/**
	 * A link to an anchor on the same web page.
	**/
	public static final class RichTextAnchorLink extends RichText {


		/**
		 * The link text.
		**/
		public RichText text;

		/**
		 * The anchor name. If the name is empty, the link must bring back to top.
		**/
		public String anchorName;

		/**
		 * An HTTP URL, opening the anchor.
		**/
		public String url;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1541418282;

		/**
		 * A link to an anchor on the same web page.
		**/
		public RichTextAnchorLink() {}

		/**
		 * A link to an anchor on the same web page.
		 *
		 * @param text The link text.
		 * @param anchorName The anchor name. If the name is empty, the link must bring back to top.
		 * @param url An HTTP URL, opening the anchor.
		**/
		public RichTextAnchorLink(RichText text, String anchorName, String url) {
			this.text = text;
			this.anchorName = anchorName;
			this.url = url;
		}

		/**
		 * A link to an anchor on the same web page.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RichTextAnchorLink(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case RichTextPlain.CONSTRUCTOR: this.text = new RichTextPlain(input); break;
					case RichTextBold.CONSTRUCTOR: this.text = new RichTextBold(input); break;
					case RichTextItalic.CONSTRUCTOR: this.text = new RichTextItalic(input); break;
					case RichTextUnderline.CONSTRUCTOR: this.text = new RichTextUnderline(input); break;
					case RichTextStrikethrough.CONSTRUCTOR: this.text = new RichTextStrikethrough(input); break;
					case RichTextFixed.CONSTRUCTOR: this.text = new RichTextFixed(input); break;
					case RichTextUrl.CONSTRUCTOR: this.text = new RichTextUrl(input); break;
					case RichTextEmailAddress.CONSTRUCTOR: this.text = new RichTextEmailAddress(input); break;
					case RichTextSubscript.CONSTRUCTOR: this.text = new RichTextSubscript(input); break;
					case RichTextSuperscript.CONSTRUCTOR: this.text = new RichTextSuperscript(input); break;
					case RichTextMarked.CONSTRUCTOR: this.text = new RichTextMarked(input); break;
					case RichTextPhoneNumber.CONSTRUCTOR: this.text = new RichTextPhoneNumber(input); break;
					case RichTextIcon.CONSTRUCTOR: this.text = new RichTextIcon(input); break;
					case RichTextReference.CONSTRUCTOR: this.text = new RichTextReference(input); break;
					case RichTextAnchor.CONSTRUCTOR: this.text = new RichTextAnchor(input); break;
					case RichTextAnchorLink.CONSTRUCTOR: this.text = new RichTextAnchorLink(input); break;
					case RichTexts.CONSTRUCTOR: this.text = new RichTexts(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				byte[] anchorNameTmp = new byte[input.readInt()];
				input.readFully(anchorNameTmp);
				this.anchorName = new String(anchorNameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] urlTmp = new byte[input.readInt()];
				input.readFully(urlTmp);
				this.url = new String(urlTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RichTextAnchorLink.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RichTextAnchorLink.CONSTRUCTOR);
			if (this.text == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.text.serialize(output);
			}
			if (this.anchorName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] anchorNameTmp = this.anchorName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(anchorNameTmp.length);
				output.write(anchorNameTmp);
			}
			if (this.url == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] urlTmp = this.url.getBytes(StandardCharsets.UTF_8);
				output.writeInt(urlTmp.length);
				output.write(urlTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			RichTextAnchorLink richTextAnchorLink = (RichTextAnchorLink) o;
			if (!Objects.equals(this.text, richTextAnchorLink.text)) {
				return false;
			}
			if (this.anchorName != richTextAnchorLink.anchorName) {
				return false;
			}
			if (this.url != richTextAnchorLink.url) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.text == null ? 0 : this.text.hashCode();
			result = result * 31 + (this.anchorName == null ? 0 : this.anchorName.hashCode());
			result = result * 31 + (this.url == null ? 0 : this.url.hashCode());
			return result;
		}
	}

	/**
	 * A concatenation of rich texts.
	**/
	public static final class RichTexts extends RichText {


		/**
		 * Texts.
		**/
		public RichText[] texts;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1647457821;

		/**
		 * A concatenation of rich texts.
		**/
		public RichTexts() {}

		/**
		 * A concatenation of rich texts.
		 *
		 * @param texts Texts.
		**/
		public RichTexts(RichText[] texts) {
			this.texts = texts;
		}

		/**
		 * A concatenation of rich texts.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RichTexts(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.texts = new RichText[input.readInt()];
				for (int i = 0; i < this.texts.length; i++) {
					switch(input.readInt()) {
						case RichTextPlain.CONSTRUCTOR: this.texts[i] = new RichTextPlain(input); break;
						case RichTextBold.CONSTRUCTOR: this.texts[i] = new RichTextBold(input); break;
						case RichTextItalic.CONSTRUCTOR: this.texts[i] = new RichTextItalic(input); break;
						case RichTextUnderline.CONSTRUCTOR: this.texts[i] = new RichTextUnderline(input); break;
						case RichTextStrikethrough.CONSTRUCTOR: this.texts[i] = new RichTextStrikethrough(input); break;
						case RichTextFixed.CONSTRUCTOR: this.texts[i] = new RichTextFixed(input); break;
						case RichTextUrl.CONSTRUCTOR: this.texts[i] = new RichTextUrl(input); break;
						case RichTextEmailAddress.CONSTRUCTOR: this.texts[i] = new RichTextEmailAddress(input); break;
						case RichTextSubscript.CONSTRUCTOR: this.texts[i] = new RichTextSubscript(input); break;
						case RichTextSuperscript.CONSTRUCTOR: this.texts[i] = new RichTextSuperscript(input); break;
						case RichTextMarked.CONSTRUCTOR: this.texts[i] = new RichTextMarked(input); break;
						case RichTextPhoneNumber.CONSTRUCTOR: this.texts[i] = new RichTextPhoneNumber(input); break;
						case RichTextIcon.CONSTRUCTOR: this.texts[i] = new RichTextIcon(input); break;
						case RichTextReference.CONSTRUCTOR: this.texts[i] = new RichTextReference(input); break;
						case RichTextAnchor.CONSTRUCTOR: this.texts[i] = new RichTextAnchor(input); break;
						case RichTextAnchorLink.CONSTRUCTOR: this.texts[i] = new RichTextAnchorLink(input); break;
						case RichTexts.CONSTRUCTOR: this.texts[i] = new RichTexts(input); break;
						default: {
							throw new UnsupportedOperationException();
						}
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RichTexts.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RichTexts.CONSTRUCTOR);
			if (this.texts == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.texts.length);
				for (int i = 0; i < this.texts.length; i++) {
					this.texts[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			RichTexts richTexts = (RichTexts) o;
			if (!Arrays.equals(this.texts, richTexts.texts)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.texts);
		}
	}

	/**
	 * Represents an RTMP URL.
	**/
	public static final class RtmpUrl extends Object {


		/**
		 * The URL.
		**/
		public String url;

		/**
		 * Stream key.
		**/
		public String streamKey;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1009302613;

		/**
		 * Represents an RTMP URL.
		**/
		public RtmpUrl() {}

		/**
		 * Represents an RTMP URL.
		 *
		 * @param url The URL.
		 * @param streamKey Stream key.
		**/
		public RtmpUrl(String url, String streamKey) {
			this.url = url;
			this.streamKey = streamKey;
		}

		/**
		 * Represents an RTMP URL.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RtmpUrl(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] urlTmp = new byte[input.readInt()];
				input.readFully(urlTmp);
				this.url = new String(urlTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] streamKeyTmp = new byte[input.readInt()];
				input.readFully(streamKeyTmp);
				this.streamKey = new String(streamKeyTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RtmpUrl.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RtmpUrl.CONSTRUCTOR);
			if (this.url == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] urlTmp = this.url.getBytes(StandardCharsets.UTF_8);
				output.writeInt(urlTmp.length);
				output.write(urlTmp);
			}
			if (this.streamKey == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] streamKeyTmp = this.streamKey.getBytes(StandardCharsets.UTF_8);
				output.writeInt(streamKeyTmp.length);
				output.write(streamKeyTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			RtmpUrl rtmpUrl = (RtmpUrl) o;
			if (this.url != rtmpUrl.url) {
				return false;
			}
			if (this.streamKey != rtmpUrl.streamKey) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.url == null ? 0 : this.url.hashCode();
			result = result * 31 + (this.streamKey == null ? 0 : this.streamKey.hashCode());
			return result;
		}
	}

	/**
	 * Contains information about saved payment credentials.
	**/
	public static final class SavedCredentials extends Object {


		/**
		 * Unique identifier of the saved credentials.
		**/
		public String id;

		/**
		 * Title of the saved credentials.
		**/
		public String title;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -370273060;

		/**
		 * Contains information about saved payment credentials.
		**/
		public SavedCredentials() {}

		/**
		 * Contains information about saved payment credentials.
		 *
		 * @param id Unique identifier of the saved credentials.
		 * @param title Title of the saved credentials.
		**/
		public SavedCredentials(String id, String title) {
			this.id = id;
			this.title = title;
		}

		/**
		 * Contains information about saved payment credentials.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SavedCredentials(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] idTmp = new byte[input.readInt()];
				input.readFully(idTmp);
				this.id = new String(idTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SavedCredentials.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SavedCredentials.CONSTRUCTOR);
			if (this.id == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] idTmp = this.id.getBytes(StandardCharsets.UTF_8);
				output.writeInt(idTmp.length);
				output.write(idTmp);
			}
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SavedCredentials savedCredentials = (SavedCredentials) o;
			if (this.id != savedCredentials.id) {
				return false;
			}
			if (this.title != savedCredentials.title) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.id == null ? 0 : this.id.hashCode();
			result = result * 31 + (this.title == null ? 0 : this.title.hashCode());
			return result;
		}
	}

	/**
	 * Contains autosave settings for an autosave settings scope.
	**/
	public static final class ScopeAutosaveSettings extends Object {


		/**
		 * True, if photo autosave is enabled.
		**/
		public boolean autosavePhotos;

		/**
		 * True, if video autosave is enabled.
		**/
		public boolean autosaveVideos;

		/**
		 * The maximum size of a video file to be autosaved, in bytes; 512 KB - 4000 MB.
		**/
		public long maxVideoFileSize;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1546821427;

		/**
		 * Contains autosave settings for an autosave settings scope.
		**/
		public ScopeAutosaveSettings() {}

		/**
		 * Contains autosave settings for an autosave settings scope.
		 *
		 * @param autosavePhotos True, if photo autosave is enabled.
		 * @param autosaveVideos True, if video autosave is enabled.
		 * @param maxVideoFileSize The maximum size of a video file to be autosaved, in bytes; 512 KB - 4000 MB.
		**/
		public ScopeAutosaveSettings(boolean autosavePhotos,
				boolean autosaveVideos,
				long maxVideoFileSize) {
			this.autosavePhotos = autosavePhotos;
			this.autosaveVideos = autosaveVideos;
			this.maxVideoFileSize = maxVideoFileSize;
		}

		/**
		 * Contains autosave settings for an autosave settings scope.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ScopeAutosaveSettings(DataInput input) throws IOException {
			this.autosavePhotos = input.readBoolean();
			this.autosaveVideos = input.readBoolean();
			this.maxVideoFileSize = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ScopeAutosaveSettings.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ScopeAutosaveSettings.CONSTRUCTOR);
			output.writeBoolean(this.autosavePhotos);
			output.writeBoolean(this.autosaveVideos);
			output.writeLong(this.maxVideoFileSize);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ScopeAutosaveSettings scopeAutosaveSettings = (ScopeAutosaveSettings) o;
			if (this.autosavePhotos != scopeAutosaveSettings.autosavePhotos) {
				return false;
			}
			if (this.autosaveVideos != scopeAutosaveSettings.autosaveVideos) {
				return false;
			}
			if (this.maxVideoFileSize != scopeAutosaveSettings.maxVideoFileSize) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.autosavePhotos);
			return result;
		}
	}

	/**
	 * Contains information about notification settings for several chats.
	**/
	public static final class ScopeNotificationSettings extends Object {


		/**
		 * Time left before notifications will be unmuted, in seconds.
		**/
		public int muteFor;

		/**
		 * Identifier of the notification sound to be played; 0 if sound is disabled.
		**/
		public long soundId;

		/**
		 * True, if message content must be displayed in notifications.
		**/
		public boolean showPreview;

		/**
		 * True, if notifications for incoming pinned messages will be created as for an ordinary unread message.
		**/
		public boolean disablePinnedMessageNotifications;

		/**
		 * True, if notifications for messages with mentions will be created as for an ordinary unread message.
		**/
		public boolean disableMentionNotifications;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1383458661;

		/**
		 * Contains information about notification settings for several chats.
		**/
		public ScopeNotificationSettings() {}

		/**
		 * Contains information about notification settings for several chats.
		 *
		 * @param muteFor Time left before notifications will be unmuted, in seconds.
		 * @param soundId Identifier of the notification sound to be played; 0 if sound is disabled.
		 * @param showPreview True, if message content must be displayed in notifications.
		 * @param disablePinnedMessageNotifications True, if notifications for incoming pinned messages will be created as for an ordinary unread message.
		 * @param disableMentionNotifications True, if notifications for messages with mentions will be created as for an ordinary unread message.
		**/
		public ScopeNotificationSettings(int muteFor,
				long soundId,
				boolean showPreview,
				boolean disablePinnedMessageNotifications,
				boolean disableMentionNotifications) {
			this.muteFor = muteFor;
			this.soundId = soundId;
			this.showPreview = showPreview;
			this.disablePinnedMessageNotifications = disablePinnedMessageNotifications;
			this.disableMentionNotifications = disableMentionNotifications;
		}

		/**
		 * Contains information about notification settings for several chats.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ScopeNotificationSettings(DataInput input) throws IOException {
			this.muteFor = input.readInt();
			this.soundId = input.readLong();
			this.showPreview = input.readBoolean();
			this.disablePinnedMessageNotifications = input.readBoolean();
			this.disableMentionNotifications = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ScopeNotificationSettings.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ScopeNotificationSettings.CONSTRUCTOR);
			output.writeInt(this.muteFor);
			output.writeLong(this.soundId);
			output.writeBoolean(this.showPreview);
			output.writeBoolean(this.disablePinnedMessageNotifications);
			output.writeBoolean(this.disableMentionNotifications);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ScopeNotificationSettings scopeNotificationSettings = (ScopeNotificationSettings) o;
			if (this.muteFor != scopeNotificationSettings.muteFor) {
				return false;
			}
			if (this.soundId != scopeNotificationSettings.soundId) {
				return false;
			}
			if (this.showPreview != scopeNotificationSettings.showPreview) {
				return false;
			}
			if (this.disablePinnedMessageNotifications != scopeNotificationSettings.disablePinnedMessageNotifications) {
				return false;
			}
			if (this.disableMentionNotifications != scopeNotificationSettings.disableMentionNotifications) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.muteFor);
			return result;
		}
	}

	/**
	 * Returns all found messages, no filter is applied.
	**/
	public static final class SearchMessagesFilterEmpty extends SearchMessagesFilter {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -869395657;

		/**
		 * Returns all found messages, no filter is applied.
		**/
		public SearchMessagesFilterEmpty() {}

		/**
		 * Returns all found messages, no filter is applied.
		 *
		**/

		/**
		 * Returns all found messages, no filter is applied.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SearchMessagesFilterEmpty(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SearchMessagesFilterEmpty.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SearchMessagesFilterEmpty.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return SearchMessagesFilterEmpty.CONSTRUCTOR;
		}
	}

	/**
	 * Returns only animation messages.
	**/
	public static final class SearchMessagesFilterAnimation extends SearchMessagesFilter {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -155713339;

		/**
		 * Returns only animation messages.
		**/
		public SearchMessagesFilterAnimation() {}

		/**
		 * Returns only animation messages.
		 *
		**/

		/**
		 * Returns only animation messages.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SearchMessagesFilterAnimation(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SearchMessagesFilterAnimation.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SearchMessagesFilterAnimation.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return SearchMessagesFilterAnimation.CONSTRUCTOR;
		}
	}

	/**
	 * Returns only audio messages.
	**/
	public static final class SearchMessagesFilterAudio extends SearchMessagesFilter {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 867505275;

		/**
		 * Returns only audio messages.
		**/
		public SearchMessagesFilterAudio() {}

		/**
		 * Returns only audio messages.
		 *
		**/

		/**
		 * Returns only audio messages.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SearchMessagesFilterAudio(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SearchMessagesFilterAudio.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SearchMessagesFilterAudio.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return SearchMessagesFilterAudio.CONSTRUCTOR;
		}
	}

	/**
	 * Returns only document messages.
	**/
	public static final class SearchMessagesFilterDocument extends SearchMessagesFilter {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1526331215;

		/**
		 * Returns only document messages.
		**/
		public SearchMessagesFilterDocument() {}

		/**
		 * Returns only document messages.
		 *
		**/

		/**
		 * Returns only document messages.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SearchMessagesFilterDocument(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SearchMessagesFilterDocument.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SearchMessagesFilterDocument.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return SearchMessagesFilterDocument.CONSTRUCTOR;
		}
	}

	/**
	 * Returns only photo messages.
	**/
	public static final class SearchMessagesFilterPhoto extends SearchMessagesFilter {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 925932293;

		/**
		 * Returns only photo messages.
		**/
		public SearchMessagesFilterPhoto() {}

		/**
		 * Returns only photo messages.
		 *
		**/

		/**
		 * Returns only photo messages.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SearchMessagesFilterPhoto(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SearchMessagesFilterPhoto.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SearchMessagesFilterPhoto.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return SearchMessagesFilterPhoto.CONSTRUCTOR;
		}
	}

	/**
	 * Returns only video messages.
	**/
	public static final class SearchMessagesFilterVideo extends SearchMessagesFilter {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 115538222;

		/**
		 * Returns only video messages.
		**/
		public SearchMessagesFilterVideo() {}

		/**
		 * Returns only video messages.
		 *
		**/

		/**
		 * Returns only video messages.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SearchMessagesFilterVideo(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SearchMessagesFilterVideo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SearchMessagesFilterVideo.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return SearchMessagesFilterVideo.CONSTRUCTOR;
		}
	}

	/**
	 * Returns only voice note messages.
	**/
	public static final class SearchMessagesFilterVoiceNote extends SearchMessagesFilter {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1841439357;

		/**
		 * Returns only voice note messages.
		**/
		public SearchMessagesFilterVoiceNote() {}

		/**
		 * Returns only voice note messages.
		 *
		**/

		/**
		 * Returns only voice note messages.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SearchMessagesFilterVoiceNote(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SearchMessagesFilterVoiceNote.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SearchMessagesFilterVoiceNote.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return SearchMessagesFilterVoiceNote.CONSTRUCTOR;
		}
	}

	/**
	 * Returns only photo and video messages.
	**/
	public static final class SearchMessagesFilterPhotoAndVideo extends SearchMessagesFilter {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1352130963;

		/**
		 * Returns only photo and video messages.
		**/
		public SearchMessagesFilterPhotoAndVideo() {}

		/**
		 * Returns only photo and video messages.
		 *
		**/

		/**
		 * Returns only photo and video messages.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SearchMessagesFilterPhotoAndVideo(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SearchMessagesFilterPhotoAndVideo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SearchMessagesFilterPhotoAndVideo.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return SearchMessagesFilterPhotoAndVideo.CONSTRUCTOR;
		}
	}

	/**
	 * Returns only messages containing URLs.
	**/
	public static final class SearchMessagesFilterUrl extends SearchMessagesFilter {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1828724341;

		/**
		 * Returns only messages containing URLs.
		**/
		public SearchMessagesFilterUrl() {}

		/**
		 * Returns only messages containing URLs.
		 *
		**/

		/**
		 * Returns only messages containing URLs.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SearchMessagesFilterUrl(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SearchMessagesFilterUrl.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SearchMessagesFilterUrl.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return SearchMessagesFilterUrl.CONSTRUCTOR;
		}
	}

	/**
	 * Returns only messages containing chat photos.
	**/
	public static final class SearchMessagesFilterChatPhoto extends SearchMessagesFilter {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1247751329;

		/**
		 * Returns only messages containing chat photos.
		**/
		public SearchMessagesFilterChatPhoto() {}

		/**
		 * Returns only messages containing chat photos.
		 *
		**/

		/**
		 * Returns only messages containing chat photos.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SearchMessagesFilterChatPhoto(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SearchMessagesFilterChatPhoto.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SearchMessagesFilterChatPhoto.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return SearchMessagesFilterChatPhoto.CONSTRUCTOR;
		}
	}

	/**
	 * Returns only video note messages.
	**/
	public static final class SearchMessagesFilterVideoNote extends SearchMessagesFilter {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 564323321;

		/**
		 * Returns only video note messages.
		**/
		public SearchMessagesFilterVideoNote() {}

		/**
		 * Returns only video note messages.
		 *
		**/

		/**
		 * Returns only video note messages.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SearchMessagesFilterVideoNote(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SearchMessagesFilterVideoNote.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SearchMessagesFilterVideoNote.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return SearchMessagesFilterVideoNote.CONSTRUCTOR;
		}
	}

	/**
	 * Returns only voice and video note messages.
	**/
	public static final class SearchMessagesFilterVoiceAndVideoNote extends SearchMessagesFilter {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 664174819;

		/**
		 * Returns only voice and video note messages.
		**/
		public SearchMessagesFilterVoiceAndVideoNote() {}

		/**
		 * Returns only voice and video note messages.
		 *
		**/

		/**
		 * Returns only voice and video note messages.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SearchMessagesFilterVoiceAndVideoNote(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SearchMessagesFilterVoiceAndVideoNote.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SearchMessagesFilterVoiceAndVideoNote.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return SearchMessagesFilterVoiceAndVideoNote.CONSTRUCTOR;
		}
	}

	/**
	 * Returns only messages with mentions of the current user, or messages
	 * that are replies to their messages.
	**/
	public static final class SearchMessagesFilterMention extends SearchMessagesFilter {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2001258652;

		/**
		 * Returns only messages with mentions of the current user, or messages that are replies to their messages.
		**/
		public SearchMessagesFilterMention() {}

		/**
		 * Returns only messages with mentions of the current user, or messages that are replies to their messages.
		 *
		**/

		/**
		 * Returns only messages with mentions of the current user, or messages that are replies to their messages.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SearchMessagesFilterMention(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SearchMessagesFilterMention.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SearchMessagesFilterMention.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return SearchMessagesFilterMention.CONSTRUCTOR;
		}
	}

	/**
	 * Returns only messages with unread mentions of the current user, or
	 * messages that are replies to their messages. When using this filter
	 * the results can&#039;t be additionally filtered by a query, a message
	 * thread or by the sending user.
	**/
	public static final class SearchMessagesFilterUnreadMention extends SearchMessagesFilter {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -95769149;

		/**
		 * Returns only messages with unread mentions of the current user, or messages that are replies to their messages. When using this filter the results can&#039;t be additionally filtered by a query, a message thread or by the sending user.
		**/
		public SearchMessagesFilterUnreadMention() {}

		/**
		 * Returns only messages with unread mentions of the current user, or messages that are replies to their messages. When using this filter the results can&#039;t be additionally filtered by a query, a message thread or by the sending user.
		 *
		**/

		/**
		 * Returns only messages with unread mentions of the current user, or messages that are replies to their messages. When using this filter the results can&#039;t be additionally filtered by a query, a message thread or by the sending user.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SearchMessagesFilterUnreadMention(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SearchMessagesFilterUnreadMention.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SearchMessagesFilterUnreadMention.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return SearchMessagesFilterUnreadMention.CONSTRUCTOR;
		}
	}

	/**
	 * Returns only messages with unread reactions for the current user.
	 * When using this filter the results can&#039;t be additionally
	 * filtered by a query, a message thread or by the sending user.
	**/
	public static final class SearchMessagesFilterUnreadReaction extends SearchMessagesFilter {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1379651328;

		/**
		 * Returns only messages with unread reactions for the current user. When using this filter the results can&#039;t be additionally filtered by a query, a message thread or by the sending user.
		**/
		public SearchMessagesFilterUnreadReaction() {}

		/**
		 * Returns only messages with unread reactions for the current user. When using this filter the results can&#039;t be additionally filtered by a query, a message thread or by the sending user.
		 *
		**/

		/**
		 * Returns only messages with unread reactions for the current user. When using this filter the results can&#039;t be additionally filtered by a query, a message thread or by the sending user.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SearchMessagesFilterUnreadReaction(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SearchMessagesFilterUnreadReaction.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SearchMessagesFilterUnreadReaction.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return SearchMessagesFilterUnreadReaction.CONSTRUCTOR;
		}
	}

	/**
	 * Returns only failed to send messages. This filter can be used only if
	 * the message database is used.
	**/
	public static final class SearchMessagesFilterFailedToSend extends SearchMessagesFilter {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -596322564;

		/**
		 * Returns only failed to send messages. This filter can be used only if the message database is used.
		**/
		public SearchMessagesFilterFailedToSend() {}

		/**
		 * Returns only failed to send messages. This filter can be used only if the message database is used.
		 *
		**/

		/**
		 * Returns only failed to send messages. This filter can be used only if the message database is used.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SearchMessagesFilterFailedToSend(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SearchMessagesFilterFailedToSend.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SearchMessagesFilterFailedToSend.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return SearchMessagesFilterFailedToSend.CONSTRUCTOR;
		}
	}

	/**
	 * Returns only pinned messages.
	**/
	public static final class SearchMessagesFilterPinned extends SearchMessagesFilter {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 371805512;

		/**
		 * Returns only pinned messages.
		**/
		public SearchMessagesFilterPinned() {}

		/**
		 * Returns only pinned messages.
		 *
		**/

		/**
		 * Returns only pinned messages.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SearchMessagesFilterPinned(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SearchMessagesFilterPinned.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SearchMessagesFilterPinned.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return SearchMessagesFilterPinned.CONSTRUCTOR;
		}
	}

	/**
	 * Contains a value representing a number of seconds.
	**/
	public static final class Seconds extends Object {


		/**
		 * Number of seconds.
		**/
		public double seconds;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 959899022;

		/**
		 * Contains a value representing a number of seconds.
		**/
		public Seconds() {}

		/**
		 * Contains a value representing a number of seconds.
		 *
		 * @param seconds Number of seconds.
		**/
		public Seconds(double seconds) {
			this.seconds = seconds;
		}

		/**
		 * Contains a value representing a number of seconds.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public Seconds(DataInput input) throws IOException {
			this.seconds = input.readDouble();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return Seconds.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(Seconds.CONSTRUCTOR);
			output.writeDouble(this.seconds);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			Seconds seconds = (Seconds) o;
			if (this.seconds != seconds.seconds) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Double.hashCode(this.seconds);
		}
	}

	/**
	 * Represents a secret chat.
	**/
	public static final class SecretChat extends Object {


		/**
		 * Secret chat identifier.
		**/
		public int id;

		/**
		 * Identifier of the chat partner.
		**/
		public long userId;

		/**
		 * State of the secret chat.
		**/
		public SecretChatState state;

		/**
		 * True, if the chat was created by the current user; false otherwise.
		**/
		public boolean isOutbound;

		/**
		 * Hash of the currently used key for comparison with the hash of the chat partner&#039;s key. This is a string of 36 little-endian bytes, which must be split into groups of 2 bits, each denoting a pixel of one of 4 colors FFFFFF, D5E6F3, 2D5775, and 2F99C9. The pixels must be used to make a 12x12 square image filled from left to right, top to bottom. Alternatively, the first 32 bytes of the hash can be converted to the hexadecimal format and printed as 32 2-digit hex numbers.
		**/
		public byte[] keyHash;

		/**
		 * Secret chat layer; determines features supported by the chat partner&#039;s application. Nested text entities and underline and strikethrough entities are supported if the layer &gt;= 101, files bigger than 2000MB are supported if the layer &gt;= 143, spoiler and custom emoji text entities are supported if the layer &gt;= 144.
		**/
		public int layer;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -676918325;

		/**
		 * Represents a secret chat.
		**/
		public SecretChat() {}

		/**
		 * Represents a secret chat.
		 *
		 * @param id Secret chat identifier.
		 * @param userId Identifier of the chat partner.
		 * @param state State of the secret chat.
		 * @param isOutbound True, if the chat was created by the current user; false otherwise.
		 * @param keyHash Hash of the currently used key for comparison with the hash of the chat partner&#039;s key. This is a string of 36 little-endian bytes, which must be split into groups of 2 bits, each denoting a pixel of one of 4 colors FFFFFF, D5E6F3, 2D5775, and 2F99C9. The pixels must be used to make a 12x12 square image filled from left to right, top to bottom. Alternatively, the first 32 bytes of the hash can be converted to the hexadecimal format and printed as 32 2-digit hex numbers.
		 * @param layer Secret chat layer; determines features supported by the chat partner&#039;s application. Nested text entities and underline and strikethrough entities are supported if the layer &gt;= 101, files bigger than 2000MB are supported if the layer &gt;= 143, spoiler and custom emoji text entities are supported if the layer &gt;= 144.
		**/
		public SecretChat(int id,
				long userId,
				SecretChatState state,
				boolean isOutbound,
				byte[] keyHash,
				int layer) {
			this.id = id;
			this.userId = userId;
			this.state = state;
			this.isOutbound = isOutbound;
			this.keyHash = keyHash;
			this.layer = layer;
		}

		/**
		 * Represents a secret chat.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SecretChat(DataInput input) throws IOException {
			this.id = input.readInt();
			this.userId = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case SecretChatStatePending.CONSTRUCTOR: this.state = new SecretChatStatePending(input); break;
					case SecretChatStateReady.CONSTRUCTOR: this.state = new SecretChatStateReady(input); break;
					case SecretChatStateClosed.CONSTRUCTOR: this.state = new SecretChatStateClosed(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.isOutbound = input.readBoolean();
			if (input.readBoolean()) {
				this.keyHash = new byte[input.readInt()];
				input.readFully(this.keyHash);
			}
			this.layer = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SecretChat.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SecretChat.CONSTRUCTOR);
			output.writeInt(this.id);
			output.writeLong(this.userId);
			if (this.state == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.state.serialize(output);
			}
			output.writeBoolean(this.isOutbound);
			if (this.keyHash == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.keyHash.length);
				output.write(this.keyHash);
			}
			output.writeInt(this.layer);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SecretChat secretChat = (SecretChat) o;
			if (this.id != secretChat.id) {
				return false;
			}
			if (this.userId != secretChat.userId) {
				return false;
			}
			if (!Objects.equals(this.state, secretChat.state)) {
				return false;
			}
			if (this.isOutbound != secretChat.isOutbound) {
				return false;
			}
			if (this.keyHash != secretChat.keyHash) {
				return false;
			}
			if (this.layer != secretChat.layer) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.id);
			result = result * 31 + (this.state == null ? 0 : this.state.hashCode());
			result = result * 31 + (Arrays.hashCode(this.keyHash));
			return result;
		}
	}

	/**
	 * The secret chat is not yet created; waiting for the other user to get
	 * online.
	**/
	public static final class SecretChatStatePending extends SecretChatState {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1637050756;

		/**
		 * The secret chat is not yet created; waiting for the other user to get online.
		**/
		public SecretChatStatePending() {}

		/**
		 * The secret chat is not yet created; waiting for the other user to get online.
		 *
		**/

		/**
		 * The secret chat is not yet created; waiting for the other user to get online.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SecretChatStatePending(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SecretChatStatePending.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SecretChatStatePending.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return SecretChatStatePending.CONSTRUCTOR;
		}
	}

	/**
	 * The secret chat is ready to use.
	**/
	public static final class SecretChatStateReady extends SecretChatState {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1611352087;

		/**
		 * The secret chat is ready to use.
		**/
		public SecretChatStateReady() {}

		/**
		 * The secret chat is ready to use.
		 *
		**/

		/**
		 * The secret chat is ready to use.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SecretChatStateReady(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SecretChatStateReady.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SecretChatStateReady.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return SecretChatStateReady.CONSTRUCTOR;
		}
	}

	/**
	 * The secret chat is closed.
	**/
	public static final class SecretChatStateClosed extends SecretChatState {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1945106707;

		/**
		 * The secret chat is closed.
		**/
		public SecretChatStateClosed() {}

		/**
		 * The secret chat is closed.
		 *
		**/

		/**
		 * The secret chat is closed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SecretChatStateClosed(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SecretChatStateClosed.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SecretChatStateClosed.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return SecretChatStateClosed.CONSTRUCTOR;
		}
	}

	/**
	 * Information about the message sent by answerWebAppQuery.
	**/
	public static final class SentWebAppMessage extends Object {


		/**
		 * Identifier of the sent inline message, if known.
		**/
		public String inlineMessageId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1243934400;

		/**
		 * Information about the message sent by answerWebAppQuery.
		**/
		public SentWebAppMessage() {}

		/**
		 * Information about the message sent by answerWebAppQuery.
		 *
		 * @param inlineMessageId Identifier of the sent inline message, if known.
		**/
		public SentWebAppMessage(String inlineMessageId) {
			this.inlineMessageId = inlineMessageId;
		}

		/**
		 * Information about the message sent by answerWebAppQuery.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SentWebAppMessage(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] inlineMessageIdTmp = new byte[input.readInt()];
				input.readFully(inlineMessageIdTmp);
				this.inlineMessageId = new String(inlineMessageIdTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SentWebAppMessage.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SentWebAppMessage.CONSTRUCTOR);
			if (this.inlineMessageId == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] inlineMessageIdTmp = this.inlineMessageId.getBytes(StandardCharsets.UTF_8);
				output.writeInt(inlineMessageIdTmp.length);
				output.write(inlineMessageIdTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SentWebAppMessage sentWebAppMessage = (SentWebAppMessage) o;
			if (this.inlineMessageId != sentWebAppMessage.inlineMessageId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.inlineMessageId == null ? 0 : this.inlineMessageId.hashCode();
		}
	}

	/**
	 * Contains information about one session in a Telegram application used
	 * by the current user. Sessions must be shown to the user in the
	 * returned order.
	**/
	public static final class Session extends Object {


		/**
		 * Session identifier.
		**/
		public long id;

		/**
		 * True, if this session is the current session.
		**/
		public boolean isCurrent;

		/**
		 * True, if a 2-step verification password is needed to complete authorization of the session.
		**/
		public boolean isPasswordPending;

		/**
		 * True, if incoming secret chats can be accepted by the session.
		**/
		public boolean canAcceptSecretChats;

		/**
		 * True, if incoming calls can be accepted by the session.
		**/
		public boolean canAcceptCalls;

		/**
		 * Session type based on the system and application version, which can be used to display a corresponding icon.
		**/
		public SessionType type;

		/**
		 * Telegram API identifier, as provided by the application.
		**/
		public int apiId;

		/**
		 * Name of the application, as provided by the application.
		**/
		public String applicationName;

		/**
		 * The version of the application, as provided by the application.
		**/
		public String applicationVersion;

		/**
		 * True, if the application is an official application or uses the apiId of an official application.
		**/
		public boolean isOfficialApplication;

		/**
		 * Model of the device the application has been run or is running on, as provided by the application.
		**/
		public String deviceModel;

		/**
		 * Operating system the application has been run or is running on, as provided by the application.
		**/
		public String platform;

		/**
		 * Version of the operating system the application has been run or is running on, as provided by the application.
		**/
		public String systemVersion;

		/**
		 * Point in time (Unix timestamp) when the user has logged in.
		**/
		public int logInDate;

		/**
		 * Point in time (Unix timestamp) when the session was last used.
		**/
		public int lastActiveDate;

		/**
		 * IP address from which the session was created, in human-readable format.
		**/
		public String ip;

		/**
		 * A two-letter country code for the country from which the session was created, based on the IP address.
		**/
		public String country;

		/**
		 * Region code from which the session was created, based on the IP address.
		**/
		public String region;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1961323642;

		/**
		 * Contains information about one session in a Telegram application used by the current user. Sessions must be shown to the user in the returned order.
		**/
		public Session() {}

		/**
		 * Contains information about one session in a Telegram application used by the current user. Sessions must be shown to the user in the returned order.
		 *
		 * @param id Session identifier.
		 * @param isCurrent True, if this session is the current session.
		 * @param isPasswordPending True, if a 2-step verification password is needed to complete authorization of the session.
		 * @param canAcceptSecretChats True, if incoming secret chats can be accepted by the session.
		 * @param canAcceptCalls True, if incoming calls can be accepted by the session.
		 * @param type Session type based on the system and application version, which can be used to display a corresponding icon.
		 * @param apiId Telegram API identifier, as provided by the application.
		 * @param applicationName Name of the application, as provided by the application.
		 * @param applicationVersion The version of the application, as provided by the application.
		 * @param isOfficialApplication True, if the application is an official application or uses the apiId of an official application.
		 * @param deviceModel Model of the device the application has been run or is running on, as provided by the application.
		 * @param platform Operating system the application has been run or is running on, as provided by the application.
		 * @param systemVersion Version of the operating system the application has been run or is running on, as provided by the application.
		 * @param logInDate Point in time (Unix timestamp) when the user has logged in.
		 * @param lastActiveDate Point in time (Unix timestamp) when the session was last used.
		 * @param ip IP address from which the session was created, in human-readable format.
		 * @param country A two-letter country code for the country from which the session was created, based on the IP address.
		 * @param region Region code from which the session was created, based on the IP address.
		**/
		public Session(long id,
				boolean isCurrent,
				boolean isPasswordPending,
				boolean canAcceptSecretChats,
				boolean canAcceptCalls,
				SessionType type,
				int apiId,
				String applicationName,
				String applicationVersion,
				boolean isOfficialApplication,
				String deviceModel,
				String platform,
				String systemVersion,
				int logInDate,
				int lastActiveDate,
				String ip,
				String country,
				String region) {
			this.id = id;
			this.isCurrent = isCurrent;
			this.isPasswordPending = isPasswordPending;
			this.canAcceptSecretChats = canAcceptSecretChats;
			this.canAcceptCalls = canAcceptCalls;
			this.type = type;
			this.apiId = apiId;
			this.applicationName = applicationName;
			this.applicationVersion = applicationVersion;
			this.isOfficialApplication = isOfficialApplication;
			this.deviceModel = deviceModel;
			this.platform = platform;
			this.systemVersion = systemVersion;
			this.logInDate = logInDate;
			this.lastActiveDate = lastActiveDate;
			this.ip = ip;
			this.country = country;
			this.region = region;
		}

		/**
		 * Contains information about one session in a Telegram application used by the current user. Sessions must be shown to the user in the returned order.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public Session(DataInput input) throws IOException {
			this.id = input.readLong();
			this.isCurrent = input.readBoolean();
			this.isPasswordPending = input.readBoolean();
			this.canAcceptSecretChats = input.readBoolean();
			this.canAcceptCalls = input.readBoolean();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case SessionTypeAndroid.CONSTRUCTOR: this.type = new SessionTypeAndroid(input); break;
					case SessionTypeApple.CONSTRUCTOR: this.type = new SessionTypeApple(input); break;
					case SessionTypeBrave.CONSTRUCTOR: this.type = new SessionTypeBrave(input); break;
					case SessionTypeChrome.CONSTRUCTOR: this.type = new SessionTypeChrome(input); break;
					case SessionTypeEdge.CONSTRUCTOR: this.type = new SessionTypeEdge(input); break;
					case SessionTypeFirefox.CONSTRUCTOR: this.type = new SessionTypeFirefox(input); break;
					case SessionTypeIpad.CONSTRUCTOR: this.type = new SessionTypeIpad(input); break;
					case SessionTypeIphone.CONSTRUCTOR: this.type = new SessionTypeIphone(input); break;
					case SessionTypeLinux.CONSTRUCTOR: this.type = new SessionTypeLinux(input); break;
					case SessionTypeMac.CONSTRUCTOR: this.type = new SessionTypeMac(input); break;
					case SessionTypeOpera.CONSTRUCTOR: this.type = new SessionTypeOpera(input); break;
					case SessionTypeSafari.CONSTRUCTOR: this.type = new SessionTypeSafari(input); break;
					case SessionTypeUbuntu.CONSTRUCTOR: this.type = new SessionTypeUbuntu(input); break;
					case SessionTypeUnknown.CONSTRUCTOR: this.type = new SessionTypeUnknown(input); break;
					case SessionTypeVivaldi.CONSTRUCTOR: this.type = new SessionTypeVivaldi(input); break;
					case SessionTypeWindows.CONSTRUCTOR: this.type = new SessionTypeWindows(input); break;
					case SessionTypeXbox.CONSTRUCTOR: this.type = new SessionTypeXbox(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.apiId = input.readInt();
			if (input.readBoolean()) {
				byte[] applicationNameTmp = new byte[input.readInt()];
				input.readFully(applicationNameTmp);
				this.applicationName = new String(applicationNameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] applicationVersionTmp = new byte[input.readInt()];
				input.readFully(applicationVersionTmp);
				this.applicationVersion = new String(applicationVersionTmp, StandardCharsets.UTF_8);
			}
			this.isOfficialApplication = input.readBoolean();
			if (input.readBoolean()) {
				byte[] deviceModelTmp = new byte[input.readInt()];
				input.readFully(deviceModelTmp);
				this.deviceModel = new String(deviceModelTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] platformTmp = new byte[input.readInt()];
				input.readFully(platformTmp);
				this.platform = new String(platformTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] systemVersionTmp = new byte[input.readInt()];
				input.readFully(systemVersionTmp);
				this.systemVersion = new String(systemVersionTmp, StandardCharsets.UTF_8);
			}
			this.logInDate = input.readInt();
			this.lastActiveDate = input.readInt();
			if (input.readBoolean()) {
				byte[] ipTmp = new byte[input.readInt()];
				input.readFully(ipTmp);
				this.ip = new String(ipTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] countryTmp = new byte[input.readInt()];
				input.readFully(countryTmp);
				this.country = new String(countryTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] regionTmp = new byte[input.readInt()];
				input.readFully(regionTmp);
				this.region = new String(regionTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return Session.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(Session.CONSTRUCTOR);
			output.writeLong(this.id);
			output.writeBoolean(this.isCurrent);
			output.writeBoolean(this.isPasswordPending);
			output.writeBoolean(this.canAcceptSecretChats);
			output.writeBoolean(this.canAcceptCalls);
			if (this.type == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.type.serialize(output);
			}
			output.writeInt(this.apiId);
			if (this.applicationName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] applicationNameTmp = this.applicationName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(applicationNameTmp.length);
				output.write(applicationNameTmp);
			}
			if (this.applicationVersion == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] applicationVersionTmp = this.applicationVersion.getBytes(StandardCharsets.UTF_8);
				output.writeInt(applicationVersionTmp.length);
				output.write(applicationVersionTmp);
			}
			output.writeBoolean(this.isOfficialApplication);
			if (this.deviceModel == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] deviceModelTmp = this.deviceModel.getBytes(StandardCharsets.UTF_8);
				output.writeInt(deviceModelTmp.length);
				output.write(deviceModelTmp);
			}
			if (this.platform == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] platformTmp = this.platform.getBytes(StandardCharsets.UTF_8);
				output.writeInt(platformTmp.length);
				output.write(platformTmp);
			}
			if (this.systemVersion == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] systemVersionTmp = this.systemVersion.getBytes(StandardCharsets.UTF_8);
				output.writeInt(systemVersionTmp.length);
				output.write(systemVersionTmp);
			}
			output.writeInt(this.logInDate);
			output.writeInt(this.lastActiveDate);
			if (this.ip == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] ipTmp = this.ip.getBytes(StandardCharsets.UTF_8);
				output.writeInt(ipTmp.length);
				output.write(ipTmp);
			}
			if (this.country == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] countryTmp = this.country.getBytes(StandardCharsets.UTF_8);
				output.writeInt(countryTmp.length);
				output.write(countryTmp);
			}
			if (this.region == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] regionTmp = this.region.getBytes(StandardCharsets.UTF_8);
				output.writeInt(regionTmp.length);
				output.write(regionTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			Session session = (Session) o;
			if (this.id != session.id) {
				return false;
			}
			if (this.isCurrent != session.isCurrent) {
				return false;
			}
			if (this.isPasswordPending != session.isPasswordPending) {
				return false;
			}
			if (this.canAcceptSecretChats != session.canAcceptSecretChats) {
				return false;
			}
			if (this.canAcceptCalls != session.canAcceptCalls) {
				return false;
			}
			if (!Objects.equals(this.type, session.type)) {
				return false;
			}
			if (this.apiId != session.apiId) {
				return false;
			}
			if (this.applicationName != session.applicationName) {
				return false;
			}
			if (this.applicationVersion != session.applicationVersion) {
				return false;
			}
			if (this.isOfficialApplication != session.isOfficialApplication) {
				return false;
			}
			if (this.deviceModel != session.deviceModel) {
				return false;
			}
			if (this.platform != session.platform) {
				return false;
			}
			if (this.systemVersion != session.systemVersion) {
				return false;
			}
			if (this.logInDate != session.logInDate) {
				return false;
			}
			if (this.lastActiveDate != session.lastActiveDate) {
				return false;
			}
			if (this.ip != session.ip) {
				return false;
			}
			if (this.country != session.country) {
				return false;
			}
			if (this.region != session.region) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.id);
			result = result * 31 + (this.type == null ? 0 : this.type.hashCode());
			result = result * 31 + (this.applicationName == null ? 0 : this.applicationName.hashCode());
			result = result * 31 + (this.applicationVersion == null ? 0 : this.applicationVersion.hashCode());
			result = result * 31 + (this.deviceModel == null ? 0 : this.deviceModel.hashCode());
			result = result * 31 + (this.platform == null ? 0 : this.platform.hashCode());
			result = result * 31 + (this.systemVersion == null ? 0 : this.systemVersion.hashCode());
			result = result * 31 + (this.ip == null ? 0 : this.ip.hashCode());
			result = result * 31 + (this.country == null ? 0 : this.country.hashCode());
			result = result * 31 + (this.region == null ? 0 : this.region.hashCode());
			return result;
		}
	}

	/**
	 * The session is running on an Android device.
	**/
	public static final class SessionTypeAndroid extends SessionType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2071764840;

		/**
		 * The session is running on an Android device.
		**/
		public SessionTypeAndroid() {}

		/**
		 * The session is running on an Android device.
		 *
		**/

		/**
		 * The session is running on an Android device.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SessionTypeAndroid(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SessionTypeAndroid.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SessionTypeAndroid.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return SessionTypeAndroid.CONSTRUCTOR;
		}
	}

	/**
	 * The session is running on a generic Apple device.
	**/
	public static final class SessionTypeApple extends SessionType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1818635701;

		/**
		 * The session is running on a generic Apple device.
		**/
		public SessionTypeApple() {}

		/**
		 * The session is running on a generic Apple device.
		 *
		**/

		/**
		 * The session is running on a generic Apple device.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SessionTypeApple(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SessionTypeApple.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SessionTypeApple.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return SessionTypeApple.CONSTRUCTOR;
		}
	}

	/**
	 * The session is running on the Brave browser.
	**/
	public static final class SessionTypeBrave extends SessionType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1216812563;

		/**
		 * The session is running on the Brave browser.
		**/
		public SessionTypeBrave() {}

		/**
		 * The session is running on the Brave browser.
		 *
		**/

		/**
		 * The session is running on the Brave browser.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SessionTypeBrave(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SessionTypeBrave.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SessionTypeBrave.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return SessionTypeBrave.CONSTRUCTOR;
		}
	}

	/**
	 * The session is running on the Chrome browser.
	**/
	public static final class SessionTypeChrome extends SessionType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1573464425;

		/**
		 * The session is running on the Chrome browser.
		**/
		public SessionTypeChrome() {}

		/**
		 * The session is running on the Chrome browser.
		 *
		**/

		/**
		 * The session is running on the Chrome browser.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SessionTypeChrome(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SessionTypeChrome.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SessionTypeChrome.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return SessionTypeChrome.CONSTRUCTOR;
		}
	}

	/**
	 * The session is running on the Edge browser.
	**/
	public static final class SessionTypeEdge extends SessionType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -538916005;

		/**
		 * The session is running on the Edge browser.
		**/
		public SessionTypeEdge() {}

		/**
		 * The session is running on the Edge browser.
		 *
		**/

		/**
		 * The session is running on the Edge browser.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SessionTypeEdge(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SessionTypeEdge.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SessionTypeEdge.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return SessionTypeEdge.CONSTRUCTOR;
		}
	}

	/**
	 * The session is running on the Firefox browser.
	**/
	public static final class SessionTypeFirefox extends SessionType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2122579364;

		/**
		 * The session is running on the Firefox browser.
		**/
		public SessionTypeFirefox() {}

		/**
		 * The session is running on the Firefox browser.
		 *
		**/

		/**
		 * The session is running on the Firefox browser.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SessionTypeFirefox(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SessionTypeFirefox.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SessionTypeFirefox.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return SessionTypeFirefox.CONSTRUCTOR;
		}
	}

	/**
	 * The session is running on an iPad device.
	**/
	public static final class SessionTypeIpad extends SessionType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1294647023;

		/**
		 * The session is running on an iPad device.
		**/
		public SessionTypeIpad() {}

		/**
		 * The session is running on an iPad device.
		 *
		**/

		/**
		 * The session is running on an iPad device.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SessionTypeIpad(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SessionTypeIpad.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SessionTypeIpad.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return SessionTypeIpad.CONSTRUCTOR;
		}
	}

	/**
	 * The session is running on an iPhone device.
	**/
	public static final class SessionTypeIphone extends SessionType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 97616573;

		/**
		 * The session is running on an iPhone device.
		**/
		public SessionTypeIphone() {}

		/**
		 * The session is running on an iPhone device.
		 *
		**/

		/**
		 * The session is running on an iPhone device.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SessionTypeIphone(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SessionTypeIphone.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SessionTypeIphone.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return SessionTypeIphone.CONSTRUCTOR;
		}
	}

	/**
	 * The session is running on a Linux device.
	**/
	public static final class SessionTypeLinux extends SessionType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1487422871;

		/**
		 * The session is running on a Linux device.
		**/
		public SessionTypeLinux() {}

		/**
		 * The session is running on a Linux device.
		 *
		**/

		/**
		 * The session is running on a Linux device.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SessionTypeLinux(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SessionTypeLinux.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SessionTypeLinux.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return SessionTypeLinux.CONSTRUCTOR;
		}
	}

	/**
	 * The session is running on a Mac device.
	**/
	public static final class SessionTypeMac extends SessionType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -612250975;

		/**
		 * The session is running on a Mac device.
		**/
		public SessionTypeMac() {}

		/**
		 * The session is running on a Mac device.
		 *
		**/

		/**
		 * The session is running on a Mac device.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SessionTypeMac(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SessionTypeMac.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SessionTypeMac.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return SessionTypeMac.CONSTRUCTOR;
		}
	}

	/**
	 * The session is running on the Opera browser.
	**/
	public static final class SessionTypeOpera extends SessionType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1463673734;

		/**
		 * The session is running on the Opera browser.
		**/
		public SessionTypeOpera() {}

		/**
		 * The session is running on the Opera browser.
		 *
		**/

		/**
		 * The session is running on the Opera browser.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SessionTypeOpera(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SessionTypeOpera.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SessionTypeOpera.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return SessionTypeOpera.CONSTRUCTOR;
		}
	}

	/**
	 * The session is running on the Safari browser.
	**/
	public static final class SessionTypeSafari extends SessionType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 710646873;

		/**
		 * The session is running on the Safari browser.
		**/
		public SessionTypeSafari() {}

		/**
		 * The session is running on the Safari browser.
		 *
		**/

		/**
		 * The session is running on the Safari browser.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SessionTypeSafari(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SessionTypeSafari.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SessionTypeSafari.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return SessionTypeSafari.CONSTRUCTOR;
		}
	}

	/**
	 * The session is running on an Ubuntu device.
	**/
	public static final class SessionTypeUbuntu extends SessionType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1569680069;

		/**
		 * The session is running on an Ubuntu device.
		**/
		public SessionTypeUbuntu() {}

		/**
		 * The session is running on an Ubuntu device.
		 *
		**/

		/**
		 * The session is running on an Ubuntu device.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SessionTypeUbuntu(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SessionTypeUbuntu.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SessionTypeUbuntu.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return SessionTypeUbuntu.CONSTRUCTOR;
		}
	}

	/**
	 * The session is running on an unknown type of device.
	**/
	public static final class SessionTypeUnknown extends SessionType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 233926704;

		/**
		 * The session is running on an unknown type of device.
		**/
		public SessionTypeUnknown() {}

		/**
		 * The session is running on an unknown type of device.
		 *
		**/

		/**
		 * The session is running on an unknown type of device.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SessionTypeUnknown(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SessionTypeUnknown.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SessionTypeUnknown.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return SessionTypeUnknown.CONSTRUCTOR;
		}
	}

	/**
	 * The session is running on the Vivaldi browser.
	**/
	public static final class SessionTypeVivaldi extends SessionType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1120503279;

		/**
		 * The session is running on the Vivaldi browser.
		**/
		public SessionTypeVivaldi() {}

		/**
		 * The session is running on the Vivaldi browser.
		 *
		**/

		/**
		 * The session is running on the Vivaldi browser.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SessionTypeVivaldi(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SessionTypeVivaldi.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SessionTypeVivaldi.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return SessionTypeVivaldi.CONSTRUCTOR;
		}
	}

	/**
	 * The session is running on a Windows device.
	**/
	public static final class SessionTypeWindows extends SessionType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1676512600;

		/**
		 * The session is running on a Windows device.
		**/
		public SessionTypeWindows() {}

		/**
		 * The session is running on a Windows device.
		 *
		**/

		/**
		 * The session is running on a Windows device.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SessionTypeWindows(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SessionTypeWindows.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SessionTypeWindows.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return SessionTypeWindows.CONSTRUCTOR;
		}
	}

	/**
	 * The session is running on an Xbox console.
	**/
	public static final class SessionTypeXbox extends SessionType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1856216492;

		/**
		 * The session is running on an Xbox console.
		**/
		public SessionTypeXbox() {}

		/**
		 * The session is running on an Xbox console.
		 *
		**/

		/**
		 * The session is running on an Xbox console.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SessionTypeXbox(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SessionTypeXbox.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SessionTypeXbox.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return SessionTypeXbox.CONSTRUCTOR;
		}
	}

	/**
	 * Contains a list of sessions.
	**/
	public static final class Sessions extends Object {


		/**
		 * List of sessions.
		**/
		public Session[] sessions;

		/**
		 * Number of days of inactivity before sessions will automatically be terminated; 1-366 days.
		**/
		public int inactiveSessionTtlDays;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 842912274;

		/**
		 * Contains a list of sessions.
		**/
		public Sessions() {}

		/**
		 * Contains a list of sessions.
		 *
		 * @param sessions List of sessions.
		 * @param inactiveSessionTtlDays Number of days of inactivity before sessions will automatically be terminated; 1-366 days.
		**/
		public Sessions(Session[] sessions, int inactiveSessionTtlDays) {
			this.sessions = sessions;
			this.inactiveSessionTtlDays = inactiveSessionTtlDays;
		}

		/**
		 * Contains a list of sessions.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public Sessions(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.sessions = new Session[input.readInt()];
				for (int i = 0; i < this.sessions.length; i++) {
					if (Session.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.sessions[i] = new Session(input);
				}
			}
			this.inactiveSessionTtlDays = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return Sessions.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(Sessions.CONSTRUCTOR);
			if (this.sessions == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.sessions.length);
				for (int i = 0; i < this.sessions.length; i++) {
					this.sessions[i].serialize(output);
				}
			}
			output.writeInt(this.inactiveSessionTtlDays);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			Sessions sessions = (Sessions) o;
			if (!Arrays.equals(this.sessions, sessions.sessions)) {
				return false;
			}
			if (this.inactiveSessionTtlDays != sessions.inactiveSessionTtlDays) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.inactiveSessionTtlDays);
			result = result * 31 + (Arrays.hashCode(this.sessions));
			return result;
		}
	}

	/**
	 * One shipping option.
	**/
	public static final class ShippingOption extends Object {


		/**
		 * Shipping option identifier.
		**/
		public String id;

		/**
		 * Option title.
		**/
		public String title;

		/**
		 * A list of objects used to calculate the total shipping costs.
		**/
		public LabeledPricePart[] priceParts;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1425690001;

		/**
		 * One shipping option.
		**/
		public ShippingOption() {}

		/**
		 * One shipping option.
		 *
		 * @param id Shipping option identifier.
		 * @param title Option title.
		 * @param priceParts A list of objects used to calculate the total shipping costs.
		**/
		public ShippingOption(String id, String title, LabeledPricePart[] priceParts) {
			this.id = id;
			this.title = title;
			this.priceParts = priceParts;
		}

		/**
		 * One shipping option.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ShippingOption(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] idTmp = new byte[input.readInt()];
				input.readFully(idTmp);
				this.id = new String(idTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				this.priceParts = new LabeledPricePart[input.readInt()];
				for (int i = 0; i < this.priceParts.length; i++) {
					if (LabeledPricePart.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.priceParts[i] = new LabeledPricePart(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ShippingOption.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ShippingOption.CONSTRUCTOR);
			if (this.id == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] idTmp = this.id.getBytes(StandardCharsets.UTF_8);
				output.writeInt(idTmp.length);
				output.write(idTmp);
			}
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
			if (this.priceParts == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.priceParts.length);
				for (int i = 0; i < this.priceParts.length; i++) {
					this.priceParts[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ShippingOption shippingOption = (ShippingOption) o;
			if (this.id != shippingOption.id) {
				return false;
			}
			if (this.title != shippingOption.title) {
				return false;
			}
			if (!Arrays.equals(this.priceParts, shippingOption.priceParts)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.id == null ? 0 : this.id.hashCode();
			result = result * 31 + (this.title == null ? 0 : this.title.hashCode());
			result = result * 31 + (Arrays.hashCode(this.priceParts));
			return result;
		}
	}

	/**
	 * The speech recognition is ongoing.
	**/
	public static final class SpeechRecognitionResultPending extends SpeechRecognitionResult {


		/**
		 * Partially recognized text.
		**/
		public String partialText;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1631810048;

		/**
		 * The speech recognition is ongoing.
		**/
		public SpeechRecognitionResultPending() {}

		/**
		 * The speech recognition is ongoing.
		 *
		 * @param partialText Partially recognized text.
		**/
		public SpeechRecognitionResultPending(String partialText) {
			this.partialText = partialText;
		}

		/**
		 * The speech recognition is ongoing.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SpeechRecognitionResultPending(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] partialTextTmp = new byte[input.readInt()];
				input.readFully(partialTextTmp);
				this.partialText = new String(partialTextTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SpeechRecognitionResultPending.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SpeechRecognitionResultPending.CONSTRUCTOR);
			if (this.partialText == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] partialTextTmp = this.partialText.getBytes(StandardCharsets.UTF_8);
				output.writeInt(partialTextTmp.length);
				output.write(partialTextTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SpeechRecognitionResultPending speechRecognitionResultPending = (SpeechRecognitionResultPending) o;
			if (this.partialText != speechRecognitionResultPending.partialText) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.partialText == null ? 0 : this.partialText.hashCode();
		}
	}

	/**
	 * The speech recognition successfully finished.
	**/
	public static final class SpeechRecognitionResultText extends SpeechRecognitionResult {


		/**
		 * Recognized text.
		**/
		public String text;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2132377123;

		/**
		 * The speech recognition successfully finished.
		**/
		public SpeechRecognitionResultText() {}

		/**
		 * The speech recognition successfully finished.
		 *
		 * @param text Recognized text.
		**/
		public SpeechRecognitionResultText(String text) {
			this.text = text;
		}

		/**
		 * The speech recognition successfully finished.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SpeechRecognitionResultText(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] textTmp = new byte[input.readInt()];
				input.readFully(textTmp);
				this.text = new String(textTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SpeechRecognitionResultText.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SpeechRecognitionResultText.CONSTRUCTOR);
			if (this.text == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] textTmp = this.text.getBytes(StandardCharsets.UTF_8);
				output.writeInt(textTmp.length);
				output.write(textTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SpeechRecognitionResultText speechRecognitionResultText = (SpeechRecognitionResultText) o;
			if (this.text != speechRecognitionResultText.text) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.text == null ? 0 : this.text.hashCode();
		}
	}

	/**
	 * The speech recognition failed.
	**/
	public static final class SpeechRecognitionResultError extends SpeechRecognitionResult {


		/**
		 * Recognition error.
		**/
		public Error error;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 164774908;

		/**
		 * The speech recognition failed.
		**/
		public SpeechRecognitionResultError() {}

		/**
		 * The speech recognition failed.
		 *
		 * @param error Recognition error.
		**/
		public SpeechRecognitionResultError(Error error) {
			this.error = error;
		}

		/**
		 * The speech recognition failed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SpeechRecognitionResultError(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Error.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.error = new Error(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SpeechRecognitionResultError.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SpeechRecognitionResultError.CONSTRUCTOR);
			if (this.error == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.error.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SpeechRecognitionResultError speechRecognitionResultError = (SpeechRecognitionResultError) o;
			if (!Objects.equals(this.error, speechRecognitionResultError.error)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.error == null ? 0 : this.error.hashCode();
		}
	}

	/**
	 * Describes a sponsored message.
	**/
	public static final class SponsoredMessage extends Object {


		/**
		 * Message identifier; unique for the chat to which the sponsored message belongs among both ordinary and sponsored messages.
		**/
		public long messageId;

		/**
		 * True, if the message needs to be labeled as &quot;recommended&quot; instead of &quot;sponsored&quot;.
		**/
		public boolean isRecommended;

		/**
		 * Sponsor chat identifier; 0 if the sponsor chat is accessible through an invite link.
		**/
		public long sponsorChatId;

		/**
		 * Information about the sponsor chat; may be null unless sponsorChatId == 0.
		**/
		public ChatInviteLinkInfo sponsorChatInfo;

		/**
		 * True, if the sponsor&#039;s chat photo must be shown.
		**/
		public boolean showChatPhoto;

		/**
		 * An internal link to be opened when the sponsored message is clicked; may be null if the sponsor chat needs to be opened instead.
		**/
		public InternalLinkType link;

		/**
		 * Content of the message. Currently, can be only of the type messageText.
		**/
		public MessageContent content;

		/**
		 * If non-empty, information about the sponsor to be shown along with the message.
		**/
		public String sponsorInfo;

		/**
		 * If non-empty, additional information about the sponsored message to be shown along with the message.
		**/
		public String additionalInfo;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1880036122;

		/**
		 * Describes a sponsored message.
		**/
		public SponsoredMessage() {}

		/**
		 * Describes a sponsored message.
		 *
		 * @param messageId Message identifier; unique for the chat to which the sponsored message belongs among both ordinary and sponsored messages.
		 * @param isRecommended True, if the message needs to be labeled as &quot;recommended&quot; instead of &quot;sponsored&quot;.
		 * @param sponsorChatId Sponsor chat identifier; 0 if the sponsor chat is accessible through an invite link.
		 * @param sponsorChatInfo Information about the sponsor chat; may be null unless sponsorChatId == 0.
		 * @param showChatPhoto True, if the sponsor&#039;s chat photo must be shown.
		 * @param link An internal link to be opened when the sponsored message is clicked; may be null if the sponsor chat needs to be opened instead.
		 * @param content Content of the message. Currently, can be only of the type messageText.
		 * @param sponsorInfo If non-empty, information about the sponsor to be shown along with the message.
		 * @param additionalInfo If non-empty, additional information about the sponsored message to be shown along with the message.
		**/
		public SponsoredMessage(long messageId,
				boolean isRecommended,
				long sponsorChatId,
				ChatInviteLinkInfo sponsorChatInfo,
				boolean showChatPhoto,
				InternalLinkType link,
				MessageContent content,
				String sponsorInfo,
				String additionalInfo) {
			this.messageId = messageId;
			this.isRecommended = isRecommended;
			this.sponsorChatId = sponsorChatId;
			this.sponsorChatInfo = sponsorChatInfo;
			this.showChatPhoto = showChatPhoto;
			this.link = link;
			this.content = content;
			this.sponsorInfo = sponsorInfo;
			this.additionalInfo = additionalInfo;
		}

		/**
		 * Describes a sponsored message.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SponsoredMessage(DataInput input) throws IOException {
			this.messageId = input.readLong();
			this.isRecommended = input.readBoolean();
			this.sponsorChatId = input.readLong();
			if (input.readBoolean()) {
				if (ChatInviteLinkInfo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.sponsorChatInfo = new ChatInviteLinkInfo(input);
			}
			this.showChatPhoto = input.readBoolean();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InternalLinkTypeActiveSessions.CONSTRUCTOR: this.link = new InternalLinkTypeActiveSessions(input); break;
					case InternalLinkTypeAttachmentMenuBot.CONSTRUCTOR: this.link = new InternalLinkTypeAttachmentMenuBot(input); break;
					case InternalLinkTypeAuthenticationCode.CONSTRUCTOR: this.link = new InternalLinkTypeAuthenticationCode(input); break;
					case InternalLinkTypeBackground.CONSTRUCTOR: this.link = new InternalLinkTypeBackground(input); break;
					case InternalLinkTypeBotAddToChannel.CONSTRUCTOR: this.link = new InternalLinkTypeBotAddToChannel(input); break;
					case InternalLinkTypeBotStart.CONSTRUCTOR: this.link = new InternalLinkTypeBotStart(input); break;
					case InternalLinkTypeBotStartInGroup.CONSTRUCTOR: this.link = new InternalLinkTypeBotStartInGroup(input); break;
					case InternalLinkTypeChangePhoneNumber.CONSTRUCTOR: this.link = new InternalLinkTypeChangePhoneNumber(input); break;
					case InternalLinkTypeChatFolderInvite.CONSTRUCTOR: this.link = new InternalLinkTypeChatFolderInvite(input); break;
					case InternalLinkTypeChatFolderSettings.CONSTRUCTOR: this.link = new InternalLinkTypeChatFolderSettings(input); break;
					case InternalLinkTypeChatInvite.CONSTRUCTOR: this.link = new InternalLinkTypeChatInvite(input); break;
					case InternalLinkTypeDefaultMessageAutoDeleteTimerSettings.CONSTRUCTOR: this.link = new InternalLinkTypeDefaultMessageAutoDeleteTimerSettings(input); break;
					case InternalLinkTypeEditProfileSettings.CONSTRUCTOR: this.link = new InternalLinkTypeEditProfileSettings(input); break;
					case InternalLinkTypeGame.CONSTRUCTOR: this.link = new InternalLinkTypeGame(input); break;
					case InternalLinkTypeInstantView.CONSTRUCTOR: this.link = new InternalLinkTypeInstantView(input); break;
					case InternalLinkTypeInvoice.CONSTRUCTOR: this.link = new InternalLinkTypeInvoice(input); break;
					case InternalLinkTypeLanguagePack.CONSTRUCTOR: this.link = new InternalLinkTypeLanguagePack(input); break;
					case InternalLinkTypeLanguageSettings.CONSTRUCTOR: this.link = new InternalLinkTypeLanguageSettings(input); break;
					case InternalLinkTypeMessage.CONSTRUCTOR: this.link = new InternalLinkTypeMessage(input); break;
					case InternalLinkTypeMessageDraft.CONSTRUCTOR: this.link = new InternalLinkTypeMessageDraft(input); break;
					case InternalLinkTypePassportDataRequest.CONSTRUCTOR: this.link = new InternalLinkTypePassportDataRequest(input); break;
					case InternalLinkTypePhoneNumberConfirmation.CONSTRUCTOR: this.link = new InternalLinkTypePhoneNumberConfirmation(input); break;
					case InternalLinkTypePremiumFeatures.CONSTRUCTOR: this.link = new InternalLinkTypePremiumFeatures(input); break;
					case InternalLinkTypePrivacyAndSecuritySettings.CONSTRUCTOR: this.link = new InternalLinkTypePrivacyAndSecuritySettings(input); break;
					case InternalLinkTypeProxy.CONSTRUCTOR: this.link = new InternalLinkTypeProxy(input); break;
					case InternalLinkTypePublicChat.CONSTRUCTOR: this.link = new InternalLinkTypePublicChat(input); break;
					case InternalLinkTypeQrCodeAuthentication.CONSTRUCTOR: this.link = new InternalLinkTypeQrCodeAuthentication(input); break;
					case InternalLinkTypeRestorePurchases.CONSTRUCTOR: this.link = new InternalLinkTypeRestorePurchases(input); break;
					case InternalLinkTypeSettings.CONSTRUCTOR: this.link = new InternalLinkTypeSettings(input); break;
					case InternalLinkTypeStickerSet.CONSTRUCTOR: this.link = new InternalLinkTypeStickerSet(input); break;
					case InternalLinkTypeTheme.CONSTRUCTOR: this.link = new InternalLinkTypeTheme(input); break;
					case InternalLinkTypeThemeSettings.CONSTRUCTOR: this.link = new InternalLinkTypeThemeSettings(input); break;
					case InternalLinkTypeUnknownDeepLink.CONSTRUCTOR: this.link = new InternalLinkTypeUnknownDeepLink(input); break;
					case InternalLinkTypeUnsupportedProxy.CONSTRUCTOR: this.link = new InternalLinkTypeUnsupportedProxy(input); break;
					case InternalLinkTypeUserPhoneNumber.CONSTRUCTOR: this.link = new InternalLinkTypeUserPhoneNumber(input); break;
					case InternalLinkTypeUserToken.CONSTRUCTOR: this.link = new InternalLinkTypeUserToken(input); break;
					case InternalLinkTypeVideoChat.CONSTRUCTOR: this.link = new InternalLinkTypeVideoChat(input); break;
					case InternalLinkTypeWebApp.CONSTRUCTOR: this.link = new InternalLinkTypeWebApp(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case MessageText.CONSTRUCTOR: this.content = new MessageText(input); break;
					case MessageAnimation.CONSTRUCTOR: this.content = new MessageAnimation(input); break;
					case MessageAudio.CONSTRUCTOR: this.content = new MessageAudio(input); break;
					case MessageDocument.CONSTRUCTOR: this.content = new MessageDocument(input); break;
					case MessagePhoto.CONSTRUCTOR: this.content = new MessagePhoto(input); break;
					case MessageExpiredPhoto.CONSTRUCTOR: this.content = new MessageExpiredPhoto(input); break;
					case MessageSticker.CONSTRUCTOR: this.content = new MessageSticker(input); break;
					case MessageVideo.CONSTRUCTOR: this.content = new MessageVideo(input); break;
					case MessageExpiredVideo.CONSTRUCTOR: this.content = new MessageExpiredVideo(input); break;
					case MessageVideoNote.CONSTRUCTOR: this.content = new MessageVideoNote(input); break;
					case MessageVoiceNote.CONSTRUCTOR: this.content = new MessageVoiceNote(input); break;
					case MessageLocation.CONSTRUCTOR: this.content = new MessageLocation(input); break;
					case MessageVenue.CONSTRUCTOR: this.content = new MessageVenue(input); break;
					case MessageContact.CONSTRUCTOR: this.content = new MessageContact(input); break;
					case MessageAnimatedEmoji.CONSTRUCTOR: this.content = new MessageAnimatedEmoji(input); break;
					case MessageDice.CONSTRUCTOR: this.content = new MessageDice(input); break;
					case MessageGame.CONSTRUCTOR: this.content = new MessageGame(input); break;
					case MessagePoll.CONSTRUCTOR: this.content = new MessagePoll(input); break;
					case MessageInvoice.CONSTRUCTOR: this.content = new MessageInvoice(input); break;
					case MessageCall.CONSTRUCTOR: this.content = new MessageCall(input); break;
					case MessageVideoChatScheduled.CONSTRUCTOR: this.content = new MessageVideoChatScheduled(input); break;
					case MessageVideoChatStarted.CONSTRUCTOR: this.content = new MessageVideoChatStarted(input); break;
					case MessageVideoChatEnded.CONSTRUCTOR: this.content = new MessageVideoChatEnded(input); break;
					case MessageInviteVideoChatParticipants.CONSTRUCTOR: this.content = new MessageInviteVideoChatParticipants(input); break;
					case MessageBasicGroupChatCreate.CONSTRUCTOR: this.content = new MessageBasicGroupChatCreate(input); break;
					case MessageSupergroupChatCreate.CONSTRUCTOR: this.content = new MessageSupergroupChatCreate(input); break;
					case MessageChatChangeTitle.CONSTRUCTOR: this.content = new MessageChatChangeTitle(input); break;
					case MessageChatChangePhoto.CONSTRUCTOR: this.content = new MessageChatChangePhoto(input); break;
					case MessageChatDeletePhoto.CONSTRUCTOR: this.content = new MessageChatDeletePhoto(input); break;
					case MessageChatAddMembers.CONSTRUCTOR: this.content = new MessageChatAddMembers(input); break;
					case MessageChatJoinByLink.CONSTRUCTOR: this.content = new MessageChatJoinByLink(input); break;
					case MessageChatJoinByRequest.CONSTRUCTOR: this.content = new MessageChatJoinByRequest(input); break;
					case MessageChatDeleteMember.CONSTRUCTOR: this.content = new MessageChatDeleteMember(input); break;
					case MessageChatUpgradeTo.CONSTRUCTOR: this.content = new MessageChatUpgradeTo(input); break;
					case MessageChatUpgradeFrom.CONSTRUCTOR: this.content = new MessageChatUpgradeFrom(input); break;
					case MessagePinMessage.CONSTRUCTOR: this.content = new MessagePinMessage(input); break;
					case MessageScreenshotTaken.CONSTRUCTOR: this.content = new MessageScreenshotTaken(input); break;
					case MessageChatSetBackground.CONSTRUCTOR: this.content = new MessageChatSetBackground(input); break;
					case MessageChatSetTheme.CONSTRUCTOR: this.content = new MessageChatSetTheme(input); break;
					case MessageChatSetMessageAutoDeleteTime.CONSTRUCTOR: this.content = new MessageChatSetMessageAutoDeleteTime(input); break;
					case MessageForumTopicCreated.CONSTRUCTOR: this.content = new MessageForumTopicCreated(input); break;
					case MessageForumTopicEdited.CONSTRUCTOR: this.content = new MessageForumTopicEdited(input); break;
					case MessageForumTopicIsClosedToggled.CONSTRUCTOR: this.content = new MessageForumTopicIsClosedToggled(input); break;
					case MessageForumTopicIsHiddenToggled.CONSTRUCTOR: this.content = new MessageForumTopicIsHiddenToggled(input); break;
					case MessageSuggestProfilePhoto.CONSTRUCTOR: this.content = new MessageSuggestProfilePhoto(input); break;
					case MessageCustomServiceAction.CONSTRUCTOR: this.content = new MessageCustomServiceAction(input); break;
					case MessageGameScore.CONSTRUCTOR: this.content = new MessageGameScore(input); break;
					case MessagePaymentSuccessful.CONSTRUCTOR: this.content = new MessagePaymentSuccessful(input); break;
					case MessagePaymentSuccessfulBot.CONSTRUCTOR: this.content = new MessagePaymentSuccessfulBot(input); break;
					case MessageGiftedPremium.CONSTRUCTOR: this.content = new MessageGiftedPremium(input); break;
					case MessageContactRegistered.CONSTRUCTOR: this.content = new MessageContactRegistered(input); break;
					case MessageUserShared.CONSTRUCTOR: this.content = new MessageUserShared(input); break;
					case MessageChatShared.CONSTRUCTOR: this.content = new MessageChatShared(input); break;
					case MessageWebsiteConnected.CONSTRUCTOR: this.content = new MessageWebsiteConnected(input); break;
					case MessageBotWriteAccessAllowed.CONSTRUCTOR: this.content = new MessageBotWriteAccessAllowed(input); break;
					case MessageWebAppDataSent.CONSTRUCTOR: this.content = new MessageWebAppDataSent(input); break;
					case MessageWebAppDataReceived.CONSTRUCTOR: this.content = new MessageWebAppDataReceived(input); break;
					case MessagePassportDataSent.CONSTRUCTOR: this.content = new MessagePassportDataSent(input); break;
					case MessagePassportDataReceived.CONSTRUCTOR: this.content = new MessagePassportDataReceived(input); break;
					case MessageProximityAlertTriggered.CONSTRUCTOR: this.content = new MessageProximityAlertTriggered(input); break;
					case MessageUnsupported.CONSTRUCTOR: this.content = new MessageUnsupported(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				byte[] sponsorInfoTmp = new byte[input.readInt()];
				input.readFully(sponsorInfoTmp);
				this.sponsorInfo = new String(sponsorInfoTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] additionalInfoTmp = new byte[input.readInt()];
				input.readFully(additionalInfoTmp);
				this.additionalInfo = new String(additionalInfoTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SponsoredMessage.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SponsoredMessage.CONSTRUCTOR);
			output.writeLong(this.messageId);
			output.writeBoolean(this.isRecommended);
			output.writeLong(this.sponsorChatId);
			if (this.sponsorChatInfo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.sponsorChatInfo.serialize(output);
			}
			output.writeBoolean(this.showChatPhoto);
			if (this.link == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.link.serialize(output);
			}
			if (this.content == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.content.serialize(output);
			}
			if (this.sponsorInfo == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] sponsorInfoTmp = this.sponsorInfo.getBytes(StandardCharsets.UTF_8);
				output.writeInt(sponsorInfoTmp.length);
				output.write(sponsorInfoTmp);
			}
			if (this.additionalInfo == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] additionalInfoTmp = this.additionalInfo.getBytes(StandardCharsets.UTF_8);
				output.writeInt(additionalInfoTmp.length);
				output.write(additionalInfoTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SponsoredMessage sponsoredMessage = (SponsoredMessage) o;
			if (this.messageId != sponsoredMessage.messageId) {
				return false;
			}
			if (this.isRecommended != sponsoredMessage.isRecommended) {
				return false;
			}
			if (this.sponsorChatId != sponsoredMessage.sponsorChatId) {
				return false;
			}
			if (!Objects.equals(this.sponsorChatInfo, sponsoredMessage.sponsorChatInfo)) {
				return false;
			}
			if (this.showChatPhoto != sponsoredMessage.showChatPhoto) {
				return false;
			}
			if (!Objects.equals(this.link, sponsoredMessage.link)) {
				return false;
			}
			if (!Objects.equals(this.content, sponsoredMessage.content)) {
				return false;
			}
			if (this.sponsorInfo != sponsoredMessage.sponsorInfo) {
				return false;
			}
			if (this.additionalInfo != sponsoredMessage.additionalInfo) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.messageId);
			result = result * 31 + (this.sponsorChatInfo == null ? 0 : this.sponsorChatInfo.hashCode());
			result = result * 31 + (this.link == null ? 0 : this.link.hashCode());
			result = result * 31 + (this.content == null ? 0 : this.content.hashCode());
			result = result * 31 + (this.sponsorInfo == null ? 0 : this.sponsorInfo.hashCode());
			result = result * 31 + (this.additionalInfo == null ? 0 : this.additionalInfo.hashCode());
			return result;
		}
	}

	/**
	 * Contains a list of sponsored messages.
	**/
	public static final class SponsoredMessages extends Object {


		/**
		 * List of sponsored messages.
		**/
		public SponsoredMessage[] messages;

		/**
		 * The minimum number of messages between shown sponsored messages, or 0 if only one sponsored message must be shown after all ordinary messages.
		**/
		public int messagesBetween;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -537674389;

		/**
		 * Contains a list of sponsored messages.
		**/
		public SponsoredMessages() {}

		/**
		 * Contains a list of sponsored messages.
		 *
		 * @param messages List of sponsored messages.
		 * @param messagesBetween The minimum number of messages between shown sponsored messages, or 0 if only one sponsored message must be shown after all ordinary messages.
		**/
		public SponsoredMessages(SponsoredMessage[] messages, int messagesBetween) {
			this.messages = messages;
			this.messagesBetween = messagesBetween;
		}

		/**
		 * Contains a list of sponsored messages.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SponsoredMessages(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.messages = new SponsoredMessage[input.readInt()];
				for (int i = 0; i < this.messages.length; i++) {
					if (SponsoredMessage.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.messages[i] = new SponsoredMessage(input);
				}
			}
			this.messagesBetween = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SponsoredMessages.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SponsoredMessages.CONSTRUCTOR);
			if (this.messages == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.messages.length);
				for (int i = 0; i < this.messages.length; i++) {
					this.messages[i].serialize(output);
				}
			}
			output.writeInt(this.messagesBetween);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SponsoredMessages sponsoredMessages = (SponsoredMessages) o;
			if (!Arrays.equals(this.messages, sponsoredMessages.messages)) {
				return false;
			}
			if (this.messagesBetween != sponsoredMessages.messagesBetween) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.messagesBetween);
			result = result * 31 + (Arrays.hashCode(this.messages));
			return result;
		}
	}

	/**
	 * A graph data.
	**/
	public static final class StatisticalGraphData extends StatisticalGraph {


		/**
		 * Graph data in JSON format.
		**/
		public String jsonData;

		/**
		 * If non-empty, a token which can be used to receive a zoomed in graph.
		**/
		public String zoomToken;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1988940244;

		/**
		 * A graph data.
		**/
		public StatisticalGraphData() {}

		/**
		 * A graph data.
		 *
		 * @param jsonData Graph data in JSON format.
		 * @param zoomToken If non-empty, a token which can be used to receive a zoomed in graph.
		**/
		public StatisticalGraphData(String jsonData, String zoomToken) {
			this.jsonData = jsonData;
			this.zoomToken = zoomToken;
		}

		/**
		 * A graph data.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public StatisticalGraphData(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] jsonDataTmp = new byte[input.readInt()];
				input.readFully(jsonDataTmp);
				this.jsonData = new String(jsonDataTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] zoomTokenTmp = new byte[input.readInt()];
				input.readFully(zoomTokenTmp);
				this.zoomToken = new String(zoomTokenTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return StatisticalGraphData.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(StatisticalGraphData.CONSTRUCTOR);
			if (this.jsonData == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] jsonDataTmp = this.jsonData.getBytes(StandardCharsets.UTF_8);
				output.writeInt(jsonDataTmp.length);
				output.write(jsonDataTmp);
			}
			if (this.zoomToken == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] zoomTokenTmp = this.zoomToken.getBytes(StandardCharsets.UTF_8);
				output.writeInt(zoomTokenTmp.length);
				output.write(zoomTokenTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			StatisticalGraphData statisticalGraphData = (StatisticalGraphData) o;
			if (this.jsonData != statisticalGraphData.jsonData) {
				return false;
			}
			if (this.zoomToken != statisticalGraphData.zoomToken) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.jsonData == null ? 0 : this.jsonData.hashCode();
			result = result * 31 + (this.zoomToken == null ? 0 : this.zoomToken.hashCode());
			return result;
		}
	}

	/**
	 * The graph data to be asynchronously loaded through
	 * getStatisticalGraph.
	**/
	public static final class StatisticalGraphAsync extends StatisticalGraph {


		/**
		 * The token to use for data loading.
		**/
		public String token;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 435891103;

		/**
		 * The graph data to be asynchronously loaded through getStatisticalGraph.
		**/
		public StatisticalGraphAsync() {}

		/**
		 * The graph data to be asynchronously loaded through getStatisticalGraph.
		 *
		 * @param token The token to use for data loading.
		**/
		public StatisticalGraphAsync(String token) {
			this.token = token;
		}

		/**
		 * The graph data to be asynchronously loaded through getStatisticalGraph.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public StatisticalGraphAsync(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] tokenTmp = new byte[input.readInt()];
				input.readFully(tokenTmp);
				this.token = new String(tokenTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return StatisticalGraphAsync.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(StatisticalGraphAsync.CONSTRUCTOR);
			if (this.token == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] tokenTmp = this.token.getBytes(StandardCharsets.UTF_8);
				output.writeInt(tokenTmp.length);
				output.write(tokenTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			StatisticalGraphAsync statisticalGraphAsync = (StatisticalGraphAsync) o;
			if (this.token != statisticalGraphAsync.token) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.token == null ? 0 : this.token.hashCode();
		}
	}

	/**
	 * An error message to be shown to the user instead of the graph.
	**/
	public static final class StatisticalGraphError extends StatisticalGraph {


		/**
		 * The error message.
		**/
		public String errorMessage;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1006788526;

		/**
		 * An error message to be shown to the user instead of the graph.
		**/
		public StatisticalGraphError() {}

		/**
		 * An error message to be shown to the user instead of the graph.
		 *
		 * @param errorMessage The error message.
		**/
		public StatisticalGraphError(String errorMessage) {
			this.errorMessage = errorMessage;
		}

		/**
		 * An error message to be shown to the user instead of the graph.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public StatisticalGraphError(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] errorMessageTmp = new byte[input.readInt()];
				input.readFully(errorMessageTmp);
				this.errorMessage = new String(errorMessageTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return StatisticalGraphError.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(StatisticalGraphError.CONSTRUCTOR);
			if (this.errorMessage == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] errorMessageTmp = this.errorMessage.getBytes(StandardCharsets.UTF_8);
				output.writeInt(errorMessageTmp.length);
				output.write(errorMessageTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			StatisticalGraphError statisticalGraphError = (StatisticalGraphError) o;
			if (this.errorMessage != statisticalGraphError.errorMessage) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.errorMessage == null ? 0 : this.errorMessage.hashCode();
		}
	}

	/**
	 * A value with information about its recent changes.
	**/
	public static final class StatisticalValue extends Object {


		/**
		 * The current value.
		**/
		public double value;

		/**
		 * The value for the previous day.
		**/
		public double previousValue;

		/**
		 * The growth rate of the value, as a percentage.
		**/
		public double growthRatePercentage;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1651337846;

		/**
		 * A value with information about its recent changes.
		**/
		public StatisticalValue() {}

		/**
		 * A value with information about its recent changes.
		 *
		 * @param value The current value.
		 * @param previousValue The value for the previous day.
		 * @param growthRatePercentage The growth rate of the value, as a percentage.
		**/
		public StatisticalValue(double value,
				double previousValue,
				double growthRatePercentage) {
			this.value = value;
			this.previousValue = previousValue;
			this.growthRatePercentage = growthRatePercentage;
		}

		/**
		 * A value with information about its recent changes.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public StatisticalValue(DataInput input) throws IOException {
			this.value = input.readDouble();
			this.previousValue = input.readDouble();
			this.growthRatePercentage = input.readDouble();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return StatisticalValue.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(StatisticalValue.CONSTRUCTOR);
			output.writeDouble(this.value);
			output.writeDouble(this.previousValue);
			output.writeDouble(this.growthRatePercentage);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			StatisticalValue statisticalValue = (StatisticalValue) o;
			if (this.value != statisticalValue.value) {
				return false;
			}
			if (this.previousValue != statisticalValue.previousValue) {
				return false;
			}
			if (this.growthRatePercentage != statisticalValue.growthRatePercentage) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Double.hashCode(this.value);
			return result;
		}
	}

	/**
	 * Describes a sticker.
	**/
	public static final class Sticker extends Object {


		/**
		 * Unique sticker identifier within the set; 0 if none.
		**/
		public long id;

		/**
		 * Identifier of the sticker set to which the sticker belongs; 0 if none.
		**/
		public long setId;

		/**
		 * Sticker width; as defined by the sender.
		**/
		public int width;

		/**
		 * Sticker height; as defined by the sender.
		**/
		public int height;

		/**
		 * Emoji corresponding to the sticker.
		**/
		public String emoji;

		/**
		 * Sticker format.
		**/
		public StickerFormat format;

		/**
		 * Sticker&#039;s full type.
		**/
		public StickerFullType fullType;

		/**
		 * Sticker&#039;s outline represented as a list of closed vector paths; may be empty. The coordinate system origin is in the upper-left corner.
		**/
		public ClosedVectorPath[] outline;

		/**
		 * Sticker thumbnail in WEBP or JPEG format; may be null.
		**/
		public Thumbnail thumbnail;

		/**
		 * File containing the sticker.
		**/
		public File sticker;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1155605331;

		/**
		 * Describes a sticker.
		**/
		public Sticker() {}

		/**
		 * Describes a sticker.
		 *
		 * @param id Unique sticker identifier within the set; 0 if none.
		 * @param setId Identifier of the sticker set to which the sticker belongs; 0 if none.
		 * @param width Sticker width; as defined by the sender.
		 * @param height Sticker height; as defined by the sender.
		 * @param emoji Emoji corresponding to the sticker.
		 * @param format Sticker format.
		 * @param fullType Sticker&#039;s full type.
		 * @param outline Sticker&#039;s outline represented as a list of closed vector paths; may be empty. The coordinate system origin is in the upper-left corner.
		 * @param thumbnail Sticker thumbnail in WEBP or JPEG format; may be null.
		 * @param sticker File containing the sticker.
		**/
		public Sticker(long id,
				long setId,
				int width,
				int height,
				String emoji,
				StickerFormat format,
				StickerFullType fullType,
				ClosedVectorPath[] outline,
				Thumbnail thumbnail,
				File sticker) {
			this.id = id;
			this.setId = setId;
			this.width = width;
			this.height = height;
			this.emoji = emoji;
			this.format = format;
			this.fullType = fullType;
			this.outline = outline;
			this.thumbnail = thumbnail;
			this.sticker = sticker;
		}

		/**
		 * Describes a sticker.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public Sticker(DataInput input) throws IOException {
			this.id = input.readLong();
			this.setId = input.readLong();
			this.width = input.readInt();
			this.height = input.readInt();
			if (input.readBoolean()) {
				byte[] emojiTmp = new byte[input.readInt()];
				input.readFully(emojiTmp);
				this.emoji = new String(emojiTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case StickerFormatWebp.CONSTRUCTOR: this.format = new StickerFormatWebp(input); break;
					case StickerFormatTgs.CONSTRUCTOR: this.format = new StickerFormatTgs(input); break;
					case StickerFormatWebm.CONSTRUCTOR: this.format = new StickerFormatWebm(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case StickerFullTypeRegular.CONSTRUCTOR: this.fullType = new StickerFullTypeRegular(input); break;
					case StickerFullTypeMask.CONSTRUCTOR: this.fullType = new StickerFullTypeMask(input); break;
					case StickerFullTypeCustomEmoji.CONSTRUCTOR: this.fullType = new StickerFullTypeCustomEmoji(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				this.outline = new ClosedVectorPath[input.readInt()];
				for (int i = 0; i < this.outline.length; i++) {
					if (ClosedVectorPath.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.outline[i] = new ClosedVectorPath(input);
				}
			}
			if (input.readBoolean()) {
				if (Thumbnail.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.thumbnail = new Thumbnail(input);
			}
			if (input.readBoolean()) {
				if (File.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.sticker = new File(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return Sticker.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(Sticker.CONSTRUCTOR);
			output.writeLong(this.id);
			output.writeLong(this.setId);
			output.writeInt(this.width);
			output.writeInt(this.height);
			if (this.emoji == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] emojiTmp = this.emoji.getBytes(StandardCharsets.UTF_8);
				output.writeInt(emojiTmp.length);
				output.write(emojiTmp);
			}
			if (this.format == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.format.serialize(output);
			}
			if (this.fullType == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.fullType.serialize(output);
			}
			if (this.outline == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.outline.length);
				for (int i = 0; i < this.outline.length; i++) {
					this.outline[i].serialize(output);
				}
			}
			if (this.thumbnail == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.thumbnail.serialize(output);
			}
			if (this.sticker == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.sticker.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			Sticker sticker = (Sticker) o;
			if (this.id != sticker.id) {
				return false;
			}
			if (this.setId != sticker.setId) {
				return false;
			}
			if (this.width != sticker.width) {
				return false;
			}
			if (this.height != sticker.height) {
				return false;
			}
			if (this.emoji != sticker.emoji) {
				return false;
			}
			if (!Objects.equals(this.format, sticker.format)) {
				return false;
			}
			if (!Objects.equals(this.fullType, sticker.fullType)) {
				return false;
			}
			if (!Arrays.equals(this.outline, sticker.outline)) {
				return false;
			}
			if (!Objects.equals(this.thumbnail, sticker.thumbnail)) {
				return false;
			}
			if (!Objects.equals(this.sticker, sticker.sticker)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.id);
			result = result * 31 + (this.emoji == null ? 0 : this.emoji.hashCode());
			result = result * 31 + (this.format == null ? 0 : this.format.hashCode());
			result = result * 31 + (this.fullType == null ? 0 : this.fullType.hashCode());
			result = result * 31 + (Arrays.hashCode(this.outline));
			result = result * 31 + (this.thumbnail == null ? 0 : this.thumbnail.hashCode());
			result = result * 31 + (this.sticker == null ? 0 : this.sticker.hashCode());
			return result;
		}
	}

	/**
	 * The sticker is an image in WEBP format.
	**/
	public static final class StickerFormatWebp extends StickerFormat {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2123043040;

		/**
		 * The sticker is an image in WEBP format.
		**/
		public StickerFormatWebp() {}

		/**
		 * The sticker is an image in WEBP format.
		 *
		**/

		/**
		 * The sticker is an image in WEBP format.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public StickerFormatWebp(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return StickerFormatWebp.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(StickerFormatWebp.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return StickerFormatWebp.CONSTRUCTOR;
		}
	}

	/**
	 * The sticker is an animation in TGS format.
	**/
	public static final class StickerFormatTgs extends StickerFormat {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1614588662;

		/**
		 * The sticker is an animation in TGS format.
		**/
		public StickerFormatTgs() {}

		/**
		 * The sticker is an animation in TGS format.
		 *
		**/

		/**
		 * The sticker is an animation in TGS format.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public StickerFormatTgs(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return StickerFormatTgs.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(StickerFormatTgs.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return StickerFormatTgs.CONSTRUCTOR;
		}
	}

	/**
	 * The sticker is a video in WEBM format.
	**/
	public static final class StickerFormatWebm extends StickerFormat {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2070162097;

		/**
		 * The sticker is a video in WEBM format.
		**/
		public StickerFormatWebm() {}

		/**
		 * The sticker is a video in WEBM format.
		 *
		**/

		/**
		 * The sticker is a video in WEBM format.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public StickerFormatWebm(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return StickerFormatWebm.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(StickerFormatWebm.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return StickerFormatWebm.CONSTRUCTOR;
		}
	}

	/**
	 * The sticker is a regular sticker.
	**/
	public static final class StickerFullTypeRegular extends StickerFullType {


		/**
		 * Premium animation of the sticker; may be null. If present, only Telegram Premium users can use the sticker.
		**/
		public File premiumAnimation;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2006425865;

		/**
		 * The sticker is a regular sticker.
		**/
		public StickerFullTypeRegular() {}

		/**
		 * The sticker is a regular sticker.
		 *
		 * @param premiumAnimation Premium animation of the sticker; may be null. If present, only Telegram Premium users can use the sticker.
		**/
		public StickerFullTypeRegular(File premiumAnimation) {
			this.premiumAnimation = premiumAnimation;
		}

		/**
		 * The sticker is a regular sticker.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public StickerFullTypeRegular(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (File.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.premiumAnimation = new File(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return StickerFullTypeRegular.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(StickerFullTypeRegular.CONSTRUCTOR);
			if (this.premiumAnimation == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.premiumAnimation.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			StickerFullTypeRegular stickerFullTypeRegular = (StickerFullTypeRegular) o;
			if (!Objects.equals(this.premiumAnimation, stickerFullTypeRegular.premiumAnimation)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.premiumAnimation == null ? 0 : this.premiumAnimation.hashCode();
		}
	}

	/**
	 * The sticker is a mask in WEBP format to be placed on photos or videos.
	**/
	public static final class StickerFullTypeMask extends StickerFullType {


		/**
		 * Position where the mask is placed; may be null.
		**/
		public MaskPosition maskPosition;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 652197687;

		/**
		 * The sticker is a mask in WEBP format to be placed on photos or videos.
		**/
		public StickerFullTypeMask() {}

		/**
		 * The sticker is a mask in WEBP format to be placed on photos or videos.
		 *
		 * @param maskPosition Position where the mask is placed; may be null.
		**/
		public StickerFullTypeMask(MaskPosition maskPosition) {
			this.maskPosition = maskPosition;
		}

		/**
		 * The sticker is a mask in WEBP format to be placed on photos or videos.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public StickerFullTypeMask(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (MaskPosition.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.maskPosition = new MaskPosition(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return StickerFullTypeMask.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(StickerFullTypeMask.CONSTRUCTOR);
			if (this.maskPosition == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.maskPosition.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			StickerFullTypeMask stickerFullTypeMask = (StickerFullTypeMask) o;
			if (!Objects.equals(this.maskPosition, stickerFullTypeMask.maskPosition)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.maskPosition == null ? 0 : this.maskPosition.hashCode();
		}
	}

	/**
	 * The sticker is a custom emoji to be used inside message text and
	 * caption. Currently, only Telegram Premium users can use custom emoji.
	**/
	public static final class StickerFullTypeCustomEmoji extends StickerFullType {


		/**
		 * Identifier of the custom emoji.
		**/
		public long customEmojiId;

		/**
		 * True, if the sticker must be repainted to a text color in messages, the color of the Telegram Premium badge in emoji status, white color on chat photos, or another appropriate color in other places.
		**/
		public boolean needsRepainting;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1015085653;

		/**
		 * The sticker is a custom emoji to be used inside message text and caption. Currently, only Telegram Premium users can use custom emoji.
		**/
		public StickerFullTypeCustomEmoji() {}

		/**
		 * The sticker is a custom emoji to be used inside message text and caption. Currently, only Telegram Premium users can use custom emoji.
		 *
		 * @param customEmojiId Identifier of the custom emoji.
		 * @param needsRepainting True, if the sticker must be repainted to a text color in messages, the color of the Telegram Premium badge in emoji status, white color on chat photos, or another appropriate color in other places.
		**/
		public StickerFullTypeCustomEmoji(long customEmojiId, boolean needsRepainting) {
			this.customEmojiId = customEmojiId;
			this.needsRepainting = needsRepainting;
		}

		/**
		 * The sticker is a custom emoji to be used inside message text and caption. Currently, only Telegram Premium users can use custom emoji.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public StickerFullTypeCustomEmoji(DataInput input) throws IOException {
			this.customEmojiId = input.readLong();
			this.needsRepainting = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return StickerFullTypeCustomEmoji.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(StickerFullTypeCustomEmoji.CONSTRUCTOR);
			output.writeLong(this.customEmojiId);
			output.writeBoolean(this.needsRepainting);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			StickerFullTypeCustomEmoji stickerFullTypeCustomEmoji = (StickerFullTypeCustomEmoji) o;
			if (this.customEmojiId != stickerFullTypeCustomEmoji.customEmojiId) {
				return false;
			}
			if (this.needsRepainting != stickerFullTypeCustomEmoji.needsRepainting) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.customEmojiId);
			return result;
		}
	}

	/**
	 * Represents a sticker set.
	**/
	public static final class StickerSet extends Object {


		/**
		 * Identifier of the sticker set.
		**/
		public long id;

		/**
		 * Title of the sticker set.
		**/
		public String title;

		/**
		 * Name of the sticker set.
		**/
		public String name;

		/**
		 * Sticker set thumbnail in WEBP, TGS, or WEBM format with width and height 100; may be null. The file can be downloaded only before the thumbnail is changed.
		**/
		public Thumbnail thumbnail;

		/**
		 * Sticker set thumbnail&#039;s outline represented as a list of closed vector paths; may be empty. The coordinate system origin is in the upper-left corner.
		**/
		public ClosedVectorPath[] thumbnailOutline;

		/**
		 * True, if the sticker set has been installed by the current user.
		**/
		public boolean isInstalled;

		/**
		 * True, if the sticker set has been archived. A sticker set can&#039;t be installed and archived simultaneously.
		**/
		public boolean isArchived;

		/**
		 * True, if the sticker set is official.
		**/
		public boolean isOfficial;

		/**
		 * Format of the stickers in the set.
		**/
		public StickerFormat stickerFormat;

		/**
		 * Type of the stickers in the set.
		**/
		public StickerType stickerType;

		/**
		 * True for already viewed trending sticker sets.
		**/
		public boolean isViewed;

		/**
		 * List of stickers in this set.
		**/
		public Sticker[] stickers;

		/**
		 * A list of emoji corresponding to the stickers in the same order. The list is only for informational purposes, because a sticker is always sent with a fixed emoji from the corresponding Sticker object.
		**/
		public Emojis[] emojis;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1899632064;

		/**
		 * Represents a sticker set.
		**/
		public StickerSet() {}

		/**
		 * Represents a sticker set.
		 *
		 * @param id Identifier of the sticker set.
		 * @param title Title of the sticker set.
		 * @param name Name of the sticker set.
		 * @param thumbnail Sticker set thumbnail in WEBP, TGS, or WEBM format with width and height 100; may be null. The file can be downloaded only before the thumbnail is changed.
		 * @param thumbnailOutline Sticker set thumbnail&#039;s outline represented as a list of closed vector paths; may be empty. The coordinate system origin is in the upper-left corner.
		 * @param isInstalled True, if the sticker set has been installed by the current user.
		 * @param isArchived True, if the sticker set has been archived. A sticker set can&#039;t be installed and archived simultaneously.
		 * @param isOfficial True, if the sticker set is official.
		 * @param stickerFormat Format of the stickers in the set.
		 * @param stickerType Type of the stickers in the set.
		 * @param isViewed True for already viewed trending sticker sets.
		 * @param stickers List of stickers in this set.
		 * @param emojis A list of emoji corresponding to the stickers in the same order. The list is only for informational purposes, because a sticker is always sent with a fixed emoji from the corresponding Sticker object.
		**/
		public StickerSet(long id,
				String title,
				String name,
				Thumbnail thumbnail,
				ClosedVectorPath[] thumbnailOutline,
				boolean isInstalled,
				boolean isArchived,
				boolean isOfficial,
				StickerFormat stickerFormat,
				StickerType stickerType,
				boolean isViewed,
				Sticker[] stickers,
				Emojis[] emojis) {
			this.id = id;
			this.title = title;
			this.name = name;
			this.thumbnail = thumbnail;
			this.thumbnailOutline = thumbnailOutline;
			this.isInstalled = isInstalled;
			this.isArchived = isArchived;
			this.isOfficial = isOfficial;
			this.stickerFormat = stickerFormat;
			this.stickerType = stickerType;
			this.isViewed = isViewed;
			this.stickers = stickers;
			this.emojis = emojis;
		}

		/**
		 * Represents a sticker set.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public StickerSet(DataInput input) throws IOException {
			this.id = input.readLong();
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] nameTmp = new byte[input.readInt()];
				input.readFully(nameTmp);
				this.name = new String(nameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (Thumbnail.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.thumbnail = new Thumbnail(input);
			}
			if (input.readBoolean()) {
				this.thumbnailOutline = new ClosedVectorPath[input.readInt()];
				for (int i = 0; i < this.thumbnailOutline.length; i++) {
					if (ClosedVectorPath.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.thumbnailOutline[i] = new ClosedVectorPath(input);
				}
			}
			this.isInstalled = input.readBoolean();
			this.isArchived = input.readBoolean();
			this.isOfficial = input.readBoolean();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case StickerFormatWebp.CONSTRUCTOR: this.stickerFormat = new StickerFormatWebp(input); break;
					case StickerFormatTgs.CONSTRUCTOR: this.stickerFormat = new StickerFormatTgs(input); break;
					case StickerFormatWebm.CONSTRUCTOR: this.stickerFormat = new StickerFormatWebm(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case StickerTypeRegular.CONSTRUCTOR: this.stickerType = new StickerTypeRegular(input); break;
					case StickerTypeMask.CONSTRUCTOR: this.stickerType = new StickerTypeMask(input); break;
					case StickerTypeCustomEmoji.CONSTRUCTOR: this.stickerType = new StickerTypeCustomEmoji(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.isViewed = input.readBoolean();
			if (input.readBoolean()) {
				this.stickers = new Sticker[input.readInt()];
				for (int i = 0; i < this.stickers.length; i++) {
					if (Sticker.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.stickers[i] = new Sticker(input);
				}
			}
			if (input.readBoolean()) {
				this.emojis = new Emojis[input.readInt()];
				for (int i = 0; i < this.emojis.length; i++) {
					if (Emojis.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.emojis[i] = new Emojis(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return StickerSet.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(StickerSet.CONSTRUCTOR);
			output.writeLong(this.id);
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
			if (this.name == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nameTmp = this.name.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nameTmp.length);
				output.write(nameTmp);
			}
			if (this.thumbnail == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.thumbnail.serialize(output);
			}
			if (this.thumbnailOutline == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.thumbnailOutline.length);
				for (int i = 0; i < this.thumbnailOutline.length; i++) {
					this.thumbnailOutline[i].serialize(output);
				}
			}
			output.writeBoolean(this.isInstalled);
			output.writeBoolean(this.isArchived);
			output.writeBoolean(this.isOfficial);
			if (this.stickerFormat == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.stickerFormat.serialize(output);
			}
			if (this.stickerType == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.stickerType.serialize(output);
			}
			output.writeBoolean(this.isViewed);
			if (this.stickers == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.stickers.length);
				for (int i = 0; i < this.stickers.length; i++) {
					this.stickers[i].serialize(output);
				}
			}
			if (this.emojis == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.emojis.length);
				for (int i = 0; i < this.emojis.length; i++) {
					this.emojis[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			StickerSet stickerSet = (StickerSet) o;
			if (this.id != stickerSet.id) {
				return false;
			}
			if (this.title != stickerSet.title) {
				return false;
			}
			if (this.name != stickerSet.name) {
				return false;
			}
			if (!Objects.equals(this.thumbnail, stickerSet.thumbnail)) {
				return false;
			}
			if (!Arrays.equals(this.thumbnailOutline, stickerSet.thumbnailOutline)) {
				return false;
			}
			if (this.isInstalled != stickerSet.isInstalled) {
				return false;
			}
			if (this.isArchived != stickerSet.isArchived) {
				return false;
			}
			if (this.isOfficial != stickerSet.isOfficial) {
				return false;
			}
			if (!Objects.equals(this.stickerFormat, stickerSet.stickerFormat)) {
				return false;
			}
			if (!Objects.equals(this.stickerType, stickerSet.stickerType)) {
				return false;
			}
			if (this.isViewed != stickerSet.isViewed) {
				return false;
			}
			if (!Arrays.equals(this.stickers, stickerSet.stickers)) {
				return false;
			}
			if (!Arrays.equals(this.emojis, stickerSet.emojis)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.id);
			result = result * 31 + (this.title == null ? 0 : this.title.hashCode());
			result = result * 31 + (this.name == null ? 0 : this.name.hashCode());
			result = result * 31 + (this.thumbnail == null ? 0 : this.thumbnail.hashCode());
			result = result * 31 + (Arrays.hashCode(this.thumbnailOutline));
			result = result * 31 + (this.stickerFormat == null ? 0 : this.stickerFormat.hashCode());
			result = result * 31 + (this.stickerType == null ? 0 : this.stickerType.hashCode());
			result = result * 31 + (Arrays.hashCode(this.stickers));
			result = result * 31 + (Arrays.hashCode(this.emojis));
			return result;
		}
	}

	/**
	 * Represents short information about a sticker set.
	**/
	public static final class StickerSetInfo extends Object {


		/**
		 * Identifier of the sticker set.
		**/
		public long id;

		/**
		 * Title of the sticker set.
		**/
		public String title;

		/**
		 * Name of the sticker set.
		**/
		public String name;

		/**
		 * Sticker set thumbnail in WEBP, TGS, or WEBM format with width and height 100; may be null.
		**/
		public Thumbnail thumbnail;

		/**
		 * Sticker set thumbnail&#039;s outline represented as a list of closed vector paths; may be empty. The coordinate system origin is in the upper-left corner.
		**/
		public ClosedVectorPath[] thumbnailOutline;

		/**
		 * True, if the sticker set has been installed by the current user.
		**/
		public boolean isInstalled;

		/**
		 * True, if the sticker set has been archived. A sticker set can&#039;t be installed and archived simultaneously.
		**/
		public boolean isArchived;

		/**
		 * True, if the sticker set is official.
		**/
		public boolean isOfficial;

		/**
		 * Format of the stickers in the set.
		**/
		public StickerFormat stickerFormat;

		/**
		 * Type of the stickers in the set.
		**/
		public StickerType stickerType;

		/**
		 * True for already viewed trending sticker sets.
		**/
		public boolean isViewed;

		/**
		 * Total number of stickers in the set.
		**/
		public int size;

		/**
		 * Up to the first 5 stickers from the set, depending on the context. If the application needs more stickers the full sticker set needs to be requested.
		**/
		public Sticker[] covers;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 745543121;

		/**
		 * Represents short information about a sticker set.
		**/
		public StickerSetInfo() {}

		/**
		 * Represents short information about a sticker set.
		 *
		 * @param id Identifier of the sticker set.
		 * @param title Title of the sticker set.
		 * @param name Name of the sticker set.
		 * @param thumbnail Sticker set thumbnail in WEBP, TGS, or WEBM format with width and height 100; may be null.
		 * @param thumbnailOutline Sticker set thumbnail&#039;s outline represented as a list of closed vector paths; may be empty. The coordinate system origin is in the upper-left corner.
		 * @param isInstalled True, if the sticker set has been installed by the current user.
		 * @param isArchived True, if the sticker set has been archived. A sticker set can&#039;t be installed and archived simultaneously.
		 * @param isOfficial True, if the sticker set is official.
		 * @param stickerFormat Format of the stickers in the set.
		 * @param stickerType Type of the stickers in the set.
		 * @param isViewed True for already viewed trending sticker sets.
		 * @param size Total number of stickers in the set.
		 * @param covers Up to the first 5 stickers from the set, depending on the context. If the application needs more stickers the full sticker set needs to be requested.
		**/
		public StickerSetInfo(long id,
				String title,
				String name,
				Thumbnail thumbnail,
				ClosedVectorPath[] thumbnailOutline,
				boolean isInstalled,
				boolean isArchived,
				boolean isOfficial,
				StickerFormat stickerFormat,
				StickerType stickerType,
				boolean isViewed,
				int size,
				Sticker[] covers) {
			this.id = id;
			this.title = title;
			this.name = name;
			this.thumbnail = thumbnail;
			this.thumbnailOutline = thumbnailOutline;
			this.isInstalled = isInstalled;
			this.isArchived = isArchived;
			this.isOfficial = isOfficial;
			this.stickerFormat = stickerFormat;
			this.stickerType = stickerType;
			this.isViewed = isViewed;
			this.size = size;
			this.covers = covers;
		}

		/**
		 * Represents short information about a sticker set.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public StickerSetInfo(DataInput input) throws IOException {
			this.id = input.readLong();
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] nameTmp = new byte[input.readInt()];
				input.readFully(nameTmp);
				this.name = new String(nameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (Thumbnail.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.thumbnail = new Thumbnail(input);
			}
			if (input.readBoolean()) {
				this.thumbnailOutline = new ClosedVectorPath[input.readInt()];
				for (int i = 0; i < this.thumbnailOutline.length; i++) {
					if (ClosedVectorPath.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.thumbnailOutline[i] = new ClosedVectorPath(input);
				}
			}
			this.isInstalled = input.readBoolean();
			this.isArchived = input.readBoolean();
			this.isOfficial = input.readBoolean();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case StickerFormatWebp.CONSTRUCTOR: this.stickerFormat = new StickerFormatWebp(input); break;
					case StickerFormatTgs.CONSTRUCTOR: this.stickerFormat = new StickerFormatTgs(input); break;
					case StickerFormatWebm.CONSTRUCTOR: this.stickerFormat = new StickerFormatWebm(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case StickerTypeRegular.CONSTRUCTOR: this.stickerType = new StickerTypeRegular(input); break;
					case StickerTypeMask.CONSTRUCTOR: this.stickerType = new StickerTypeMask(input); break;
					case StickerTypeCustomEmoji.CONSTRUCTOR: this.stickerType = new StickerTypeCustomEmoji(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.isViewed = input.readBoolean();
			this.size = input.readInt();
			if (input.readBoolean()) {
				this.covers = new Sticker[input.readInt()];
				for (int i = 0; i < this.covers.length; i++) {
					if (Sticker.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.covers[i] = new Sticker(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return StickerSetInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(StickerSetInfo.CONSTRUCTOR);
			output.writeLong(this.id);
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
			if (this.name == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nameTmp = this.name.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nameTmp.length);
				output.write(nameTmp);
			}
			if (this.thumbnail == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.thumbnail.serialize(output);
			}
			if (this.thumbnailOutline == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.thumbnailOutline.length);
				for (int i = 0; i < this.thumbnailOutline.length; i++) {
					this.thumbnailOutline[i].serialize(output);
				}
			}
			output.writeBoolean(this.isInstalled);
			output.writeBoolean(this.isArchived);
			output.writeBoolean(this.isOfficial);
			if (this.stickerFormat == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.stickerFormat.serialize(output);
			}
			if (this.stickerType == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.stickerType.serialize(output);
			}
			output.writeBoolean(this.isViewed);
			output.writeInt(this.size);
			if (this.covers == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.covers.length);
				for (int i = 0; i < this.covers.length; i++) {
					this.covers[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			StickerSetInfo stickerSetInfo = (StickerSetInfo) o;
			if (this.id != stickerSetInfo.id) {
				return false;
			}
			if (this.title != stickerSetInfo.title) {
				return false;
			}
			if (this.name != stickerSetInfo.name) {
				return false;
			}
			if (!Objects.equals(this.thumbnail, stickerSetInfo.thumbnail)) {
				return false;
			}
			if (!Arrays.equals(this.thumbnailOutline, stickerSetInfo.thumbnailOutline)) {
				return false;
			}
			if (this.isInstalled != stickerSetInfo.isInstalled) {
				return false;
			}
			if (this.isArchived != stickerSetInfo.isArchived) {
				return false;
			}
			if (this.isOfficial != stickerSetInfo.isOfficial) {
				return false;
			}
			if (!Objects.equals(this.stickerFormat, stickerSetInfo.stickerFormat)) {
				return false;
			}
			if (!Objects.equals(this.stickerType, stickerSetInfo.stickerType)) {
				return false;
			}
			if (this.isViewed != stickerSetInfo.isViewed) {
				return false;
			}
			if (this.size != stickerSetInfo.size) {
				return false;
			}
			if (!Arrays.equals(this.covers, stickerSetInfo.covers)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.id);
			result = result * 31 + (this.title == null ? 0 : this.title.hashCode());
			result = result * 31 + (this.name == null ? 0 : this.name.hashCode());
			result = result * 31 + (this.thumbnail == null ? 0 : this.thumbnail.hashCode());
			result = result * 31 + (Arrays.hashCode(this.thumbnailOutline));
			result = result * 31 + (this.stickerFormat == null ? 0 : this.stickerFormat.hashCode());
			result = result * 31 + (this.stickerType == null ? 0 : this.stickerType.hashCode());
			result = result * 31 + (Arrays.hashCode(this.covers));
			return result;
		}
	}

	/**
	 * Represents a list of sticker sets.
	**/
	public static final class StickerSets extends Object {


		/**
		 * Approximate total number of sticker sets found.
		**/
		public int totalCount;

		/**
		 * List of sticker sets.
		**/
		public StickerSetInfo[] sets;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1883828812;

		/**
		 * Represents a list of sticker sets.
		**/
		public StickerSets() {}

		/**
		 * Represents a list of sticker sets.
		 *
		 * @param totalCount Approximate total number of sticker sets found.
		 * @param sets List of sticker sets.
		**/
		public StickerSets(int totalCount, StickerSetInfo[] sets) {
			this.totalCount = totalCount;
			this.sets = sets;
		}

		/**
		 * Represents a list of sticker sets.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public StickerSets(DataInput input) throws IOException {
			this.totalCount = input.readInt();
			if (input.readBoolean()) {
				this.sets = new StickerSetInfo[input.readInt()];
				for (int i = 0; i < this.sets.length; i++) {
					if (StickerSetInfo.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.sets[i] = new StickerSetInfo(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return StickerSets.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(StickerSets.CONSTRUCTOR);
			output.writeInt(this.totalCount);
			if (this.sets == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.sets.length);
				for (int i = 0; i < this.sets.length; i++) {
					this.sets[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			StickerSets stickerSets = (StickerSets) o;
			if (this.totalCount != stickerSets.totalCount) {
				return false;
			}
			if (!Arrays.equals(this.sets, stickerSets.sets)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.totalCount);
			result = result * 31 + (Arrays.hashCode(this.sets));
			return result;
		}
	}

	/**
	 * The sticker is a regular sticker.
	**/
	public static final class StickerTypeRegular extends StickerType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 56345973;

		/**
		 * The sticker is a regular sticker.
		**/
		public StickerTypeRegular() {}

		/**
		 * The sticker is a regular sticker.
		 *
		**/

		/**
		 * The sticker is a regular sticker.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public StickerTypeRegular(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return StickerTypeRegular.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(StickerTypeRegular.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return StickerTypeRegular.CONSTRUCTOR;
		}
	}

	/**
	 * The sticker is a mask in WEBP format to be placed on photos or videos.
	**/
	public static final class StickerTypeMask extends StickerType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1765394796;

		/**
		 * The sticker is a mask in WEBP format to be placed on photos or videos.
		**/
		public StickerTypeMask() {}

		/**
		 * The sticker is a mask in WEBP format to be placed on photos or videos.
		 *
		**/

		/**
		 * The sticker is a mask in WEBP format to be placed on photos or videos.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public StickerTypeMask(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return StickerTypeMask.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(StickerTypeMask.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return StickerTypeMask.CONSTRUCTOR;
		}
	}

	/**
	 * The sticker is a custom emoji to be used inside message text and
	 * caption.
	**/
	public static final class StickerTypeCustomEmoji extends StickerType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -120752249;

		/**
		 * The sticker is a custom emoji to be used inside message text and caption.
		**/
		public StickerTypeCustomEmoji() {}

		/**
		 * The sticker is a custom emoji to be used inside message text and caption.
		 *
		**/

		/**
		 * The sticker is a custom emoji to be used inside message text and caption.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public StickerTypeCustomEmoji(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return StickerTypeCustomEmoji.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(StickerTypeCustomEmoji.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return StickerTypeCustomEmoji.CONSTRUCTOR;
		}
	}

	/**
	 * Represents a list of stickers.
	**/
	public static final class Stickers extends Object {


		/**
		 * List of stickers.
		**/
		public Sticker[] stickers;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1974859260;

		/**
		 * Represents a list of stickers.
		**/
		public Stickers() {}

		/**
		 * Represents a list of stickers.
		 *
		 * @param stickers List of stickers.
		**/
		public Stickers(Sticker[] stickers) {
			this.stickers = stickers;
		}

		/**
		 * Represents a list of stickers.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public Stickers(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.stickers = new Sticker[input.readInt()];
				for (int i = 0; i < this.stickers.length; i++) {
					if (Sticker.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.stickers[i] = new Sticker(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return Stickers.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(Stickers.CONSTRUCTOR);
			if (this.stickers == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.stickers.length);
				for (int i = 0; i < this.stickers.length; i++) {
					this.stickers[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			Stickers stickers = (Stickers) o;
			if (!Arrays.equals(this.stickers, stickers.stickers)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.stickers);
		}
	}

	/**
	 * Contains the exact storage usage statistics split by chats and file
	 * type.
	**/
	public static final class StorageStatistics extends Object {


		/**
		 * Total size of files, in bytes.
		**/
		public long size;

		/**
		 * Total number of files.
		**/
		public int count;

		/**
		 * Statistics split by chats.
		**/
		public StorageStatisticsByChat[] byChat;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 217237013;

		/**
		 * Contains the exact storage usage statistics split by chats and file type.
		**/
		public StorageStatistics() {}

		/**
		 * Contains the exact storage usage statistics split by chats and file type.
		 *
		 * @param size Total size of files, in bytes.
		 * @param count Total number of files.
		 * @param byChat Statistics split by chats.
		**/
		public StorageStatistics(long size, int count, StorageStatisticsByChat[] byChat) {
			this.size = size;
			this.count = count;
			this.byChat = byChat;
		}

		/**
		 * Contains the exact storage usage statistics split by chats and file type.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public StorageStatistics(DataInput input) throws IOException {
			this.size = input.readLong();
			this.count = input.readInt();
			if (input.readBoolean()) {
				this.byChat = new StorageStatisticsByChat[input.readInt()];
				for (int i = 0; i < this.byChat.length; i++) {
					if (StorageStatisticsByChat.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.byChat[i] = new StorageStatisticsByChat(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return StorageStatistics.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(StorageStatistics.CONSTRUCTOR);
			output.writeLong(this.size);
			output.writeInt(this.count);
			if (this.byChat == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.byChat.length);
				for (int i = 0; i < this.byChat.length; i++) {
					this.byChat[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			StorageStatistics storageStatistics = (StorageStatistics) o;
			if (this.size != storageStatistics.size) {
				return false;
			}
			if (this.count != storageStatistics.count) {
				return false;
			}
			if (!Arrays.equals(this.byChat, storageStatistics.byChat)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.size);
			result = result * 31 + (Arrays.hashCode(this.byChat));
			return result;
		}
	}

	/**
	 * Contains the storage usage statistics for a specific chat.
	**/
	public static final class StorageStatisticsByChat extends Object {


		/**
		 * Chat identifier; 0 if none.
		**/
		public long chatId;

		/**
		 * Total size of the files in the chat, in bytes.
		**/
		public long size;

		/**
		 * Total number of files in the chat.
		**/
		public int count;

		/**
		 * Statistics split by file types.
		**/
		public StorageStatisticsByFileType[] byFileType;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 635434531;

		/**
		 * Contains the storage usage statistics for a specific chat.
		**/
		public StorageStatisticsByChat() {}

		/**
		 * Contains the storage usage statistics for a specific chat.
		 *
		 * @param chatId Chat identifier; 0 if none.
		 * @param size Total size of the files in the chat, in bytes.
		 * @param count Total number of files in the chat.
		 * @param byFileType Statistics split by file types.
		**/
		public StorageStatisticsByChat(long chatId,
				long size,
				int count,
				StorageStatisticsByFileType[] byFileType) {
			this.chatId = chatId;
			this.size = size;
			this.count = count;
			this.byFileType = byFileType;
		}

		/**
		 * Contains the storage usage statistics for a specific chat.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public StorageStatisticsByChat(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.size = input.readLong();
			this.count = input.readInt();
			if (input.readBoolean()) {
				this.byFileType = new StorageStatisticsByFileType[input.readInt()];
				for (int i = 0; i < this.byFileType.length; i++) {
					if (StorageStatisticsByFileType.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.byFileType[i] = new StorageStatisticsByFileType(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return StorageStatisticsByChat.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(StorageStatisticsByChat.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.size);
			output.writeInt(this.count);
			if (this.byFileType == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.byFileType.length);
				for (int i = 0; i < this.byFileType.length; i++) {
					this.byFileType[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			StorageStatisticsByChat storageStatisticsByChat = (StorageStatisticsByChat) o;
			if (this.chatId != storageStatisticsByChat.chatId) {
				return false;
			}
			if (this.size != storageStatisticsByChat.size) {
				return false;
			}
			if (this.count != storageStatisticsByChat.count) {
				return false;
			}
			if (!Arrays.equals(this.byFileType, storageStatisticsByChat.byFileType)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (Arrays.hashCode(this.byFileType));
			return result;
		}
	}

	/**
	 * Contains the storage usage statistics for a specific file type.
	**/
	public static final class StorageStatisticsByFileType extends Object {


		/**
		 * File type.
		**/
		public FileType fileType;

		/**
		 * Total size of the files, in bytes.
		**/
		public long size;

		/**
		 * Total number of files.
		**/
		public int count;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 714012840;

		/**
		 * Contains the storage usage statistics for a specific file type.
		**/
		public StorageStatisticsByFileType() {}

		/**
		 * Contains the storage usage statistics for a specific file type.
		 *
		 * @param fileType File type.
		 * @param size Total size of the files, in bytes.
		 * @param count Total number of files.
		**/
		public StorageStatisticsByFileType(FileType fileType, long size, int count) {
			this.fileType = fileType;
			this.size = size;
			this.count = count;
		}

		/**
		 * Contains the storage usage statistics for a specific file type.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public StorageStatisticsByFileType(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case FileTypeNone.CONSTRUCTOR: this.fileType = new FileTypeNone(input); break;
					case FileTypeAnimation.CONSTRUCTOR: this.fileType = new FileTypeAnimation(input); break;
					case FileTypeAudio.CONSTRUCTOR: this.fileType = new FileTypeAudio(input); break;
					case FileTypeDocument.CONSTRUCTOR: this.fileType = new FileTypeDocument(input); break;
					case FileTypeNotificationSound.CONSTRUCTOR: this.fileType = new FileTypeNotificationSound(input); break;
					case FileTypePhoto.CONSTRUCTOR: this.fileType = new FileTypePhoto(input); break;
					case FileTypeProfilePhoto.CONSTRUCTOR: this.fileType = new FileTypeProfilePhoto(input); break;
					case FileTypeSecret.CONSTRUCTOR: this.fileType = new FileTypeSecret(input); break;
					case FileTypeSecretThumbnail.CONSTRUCTOR: this.fileType = new FileTypeSecretThumbnail(input); break;
					case FileTypeSecure.CONSTRUCTOR: this.fileType = new FileTypeSecure(input); break;
					case FileTypeSticker.CONSTRUCTOR: this.fileType = new FileTypeSticker(input); break;
					case FileTypeThumbnail.CONSTRUCTOR: this.fileType = new FileTypeThumbnail(input); break;
					case FileTypeUnknown.CONSTRUCTOR: this.fileType = new FileTypeUnknown(input); break;
					case FileTypeVideo.CONSTRUCTOR: this.fileType = new FileTypeVideo(input); break;
					case FileTypeVideoNote.CONSTRUCTOR: this.fileType = new FileTypeVideoNote(input); break;
					case FileTypeVoiceNote.CONSTRUCTOR: this.fileType = new FileTypeVoiceNote(input); break;
					case FileTypeWallpaper.CONSTRUCTOR: this.fileType = new FileTypeWallpaper(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.size = input.readLong();
			this.count = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return StorageStatisticsByFileType.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(StorageStatisticsByFileType.CONSTRUCTOR);
			if (this.fileType == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.fileType.serialize(output);
			}
			output.writeLong(this.size);
			output.writeInt(this.count);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			StorageStatisticsByFileType storageStatisticsByFileType = (StorageStatisticsByFileType) o;
			if (!Objects.equals(this.fileType, storageStatisticsByFileType.fileType)) {
				return false;
			}
			if (this.size != storageStatisticsByFileType.size) {
				return false;
			}
			if (this.count != storageStatisticsByFileType.count) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.size);
			result = result * 31 + (this.fileType == null ? 0 : this.fileType.hashCode());
			return result;
		}
	}

	/**
	 * Contains approximate storage usage statistics, excluding files of
	 * unknown file type.
	**/
	public static final class StorageStatisticsFast extends Object {


		/**
		 * Approximate total size of files, in bytes.
		**/
		public long filesSize;

		/**
		 * Approximate number of files.
		**/
		public int fileCount;

		/**
		 * Size of the database.
		**/
		public long databaseSize;

		/**
		 * Size of the language pack database.
		**/
		public long languagePackDatabaseSize;

		/**
		 * Size of the TDLib internal log.
		**/
		public long logSize;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -884922271;

		/**
		 * Contains approximate storage usage statistics, excluding files of unknown file type.
		**/
		public StorageStatisticsFast() {}

		/**
		 * Contains approximate storage usage statistics, excluding files of unknown file type.
		 *
		 * @param filesSize Approximate total size of files, in bytes.
		 * @param fileCount Approximate number of files.
		 * @param databaseSize Size of the database.
		 * @param languagePackDatabaseSize Size of the language pack database.
		 * @param logSize Size of the TDLib internal log.
		**/
		public StorageStatisticsFast(long filesSize,
				int fileCount,
				long databaseSize,
				long languagePackDatabaseSize,
				long logSize) {
			this.filesSize = filesSize;
			this.fileCount = fileCount;
			this.databaseSize = databaseSize;
			this.languagePackDatabaseSize = languagePackDatabaseSize;
			this.logSize = logSize;
		}

		/**
		 * Contains approximate storage usage statistics, excluding files of unknown file type.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public StorageStatisticsFast(DataInput input) throws IOException {
			this.filesSize = input.readLong();
			this.fileCount = input.readInt();
			this.databaseSize = input.readLong();
			this.languagePackDatabaseSize = input.readLong();
			this.logSize = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return StorageStatisticsFast.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(StorageStatisticsFast.CONSTRUCTOR);
			output.writeLong(this.filesSize);
			output.writeInt(this.fileCount);
			output.writeLong(this.databaseSize);
			output.writeLong(this.languagePackDatabaseSize);
			output.writeLong(this.logSize);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			StorageStatisticsFast storageStatisticsFast = (StorageStatisticsFast) o;
			if (this.filesSize != storageStatisticsFast.filesSize) {
				return false;
			}
			if (this.fileCount != storageStatisticsFast.fileCount) {
				return false;
			}
			if (this.databaseSize != storageStatisticsFast.databaseSize) {
				return false;
			}
			if (this.languagePackDatabaseSize != storageStatisticsFast.languagePackDatabaseSize) {
				return false;
			}
			if (this.logSize != storageStatisticsFast.logSize) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.filesSize);
			return result;
		}
	}

	/**
	 * The user subscribed to Telegram Premium.
	**/
	public static final class StorePaymentPurposePremiumSubscription extends StorePaymentPurpose {


		/**
		 * Pass true if this is a restore of a Telegram Premium purchase; only for App Store.
		**/
		public boolean isRestore;

		/**
		 * Pass true if this is an upgrade from a monthly subscription to early subscription; only for App Store.
		**/
		public boolean isUpgrade;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1263894804;

		/**
		 * The user subscribed to Telegram Premium.
		**/
		public StorePaymentPurposePremiumSubscription() {}

		/**
		 * The user subscribed to Telegram Premium.
		 *
		 * @param isRestore Pass true if this is a restore of a Telegram Premium purchase; only for App Store.
		 * @param isUpgrade Pass true if this is an upgrade from a monthly subscription to early subscription; only for App Store.
		**/
		public StorePaymentPurposePremiumSubscription(boolean isRestore, boolean isUpgrade) {
			this.isRestore = isRestore;
			this.isUpgrade = isUpgrade;
		}

		/**
		 * The user subscribed to Telegram Premium.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public StorePaymentPurposePremiumSubscription(DataInput input) throws IOException {
			this.isRestore = input.readBoolean();
			this.isUpgrade = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return StorePaymentPurposePremiumSubscription.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(StorePaymentPurposePremiumSubscription.CONSTRUCTOR);
			output.writeBoolean(this.isRestore);
			output.writeBoolean(this.isUpgrade);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			StorePaymentPurposePremiumSubscription storePaymentPurposePremiumSubscription = (StorePaymentPurposePremiumSubscription) o;
			if (this.isRestore != storePaymentPurposePremiumSubscription.isRestore) {
				return false;
			}
			if (this.isUpgrade != storePaymentPurposePremiumSubscription.isUpgrade) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isRestore);
			return result;
		}
	}

	/**
	 * The user gifted Telegram Premium to another user.
	**/
	public static final class StorePaymentPurposeGiftedPremium extends StorePaymentPurpose {


		/**
		 * Identifier of the user for which Premium was gifted.
		**/
		public long userId;

		/**
		 * ISO 4217 currency code of the payment currency.
		**/
		public String currency;

		/**
		 * Paid amount, in the smallest units of the currency.
		**/
		public long amount;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1916846289;

		/**
		 * The user gifted Telegram Premium to another user.
		**/
		public StorePaymentPurposeGiftedPremium() {}

		/**
		 * The user gifted Telegram Premium to another user.
		 *
		 * @param userId Identifier of the user for which Premium was gifted.
		 * @param currency ISO 4217 currency code of the payment currency.
		 * @param amount Paid amount, in the smallest units of the currency.
		**/
		public StorePaymentPurposeGiftedPremium(long userId, String currency, long amount) {
			this.userId = userId;
			this.currency = currency;
			this.amount = amount;
		}

		/**
		 * The user gifted Telegram Premium to another user.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public StorePaymentPurposeGiftedPremium(DataInput input) throws IOException {
			this.userId = input.readLong();
			if (input.readBoolean()) {
				byte[] currencyTmp = new byte[input.readInt()];
				input.readFully(currencyTmp);
				this.currency = new String(currencyTmp, StandardCharsets.UTF_8);
			}
			this.amount = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return StorePaymentPurposeGiftedPremium.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(StorePaymentPurposeGiftedPremium.CONSTRUCTOR);
			output.writeLong(this.userId);
			if (this.currency == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] currencyTmp = this.currency.getBytes(StandardCharsets.UTF_8);
				output.writeInt(currencyTmp.length);
				output.write(currencyTmp);
			}
			output.writeLong(this.amount);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			StorePaymentPurposeGiftedPremium storePaymentPurposeGiftedPremium = (StorePaymentPurposeGiftedPremium) o;
			if (this.userId != storePaymentPurposeGiftedPremium.userId) {
				return false;
			}
			if (this.currency != storePaymentPurposeGiftedPremium.currency) {
				return false;
			}
			if (this.amount != storePaymentPurposeGiftedPremium.amount) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.userId);
			result = result * 31 + (this.currency == null ? 0 : this.currency.hashCode());
			return result;
		}
	}

	/**
	 * Suggests the user to enable
	 * &quot;archive_and_mute_new_chats_from_unknown_users&quot; option.
	**/
	public static final class SuggestedActionEnableArchiveAndMuteNewChats extends SuggestedAction {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2017586255;

		/**
		 * Suggests the user to enable &quot;archive_and_mute_new_chats_from_unknown_users&quot; option.
		**/
		public SuggestedActionEnableArchiveAndMuteNewChats() {}

		/**
		 * Suggests the user to enable &quot;archive_and_mute_new_chats_from_unknown_users&quot; option.
		 *
		**/

		/**
		 * Suggests the user to enable &quot;archive_and_mute_new_chats_from_unknown_users&quot; option.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SuggestedActionEnableArchiveAndMuteNewChats(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SuggestedActionEnableArchiveAndMuteNewChats.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SuggestedActionEnableArchiveAndMuteNewChats.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return SuggestedActionEnableArchiveAndMuteNewChats.CONSTRUCTOR;
		}
	}

	/**
	 * Suggests the user to check whether they still remember their 2-step
	 * verification password.
	**/
	public static final class SuggestedActionCheckPassword extends SuggestedAction {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1910534839;

		/**
		 * Suggests the user to check whether they still remember their 2-step verification password.
		**/
		public SuggestedActionCheckPassword() {}

		/**
		 * Suggests the user to check whether they still remember their 2-step verification password.
		 *
		**/

		/**
		 * Suggests the user to check whether they still remember their 2-step verification password.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SuggestedActionCheckPassword(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SuggestedActionCheckPassword.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SuggestedActionCheckPassword.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return SuggestedActionCheckPassword.CONSTRUCTOR;
		}
	}

	/**
	 * Suggests the user to check whether authorization phone number is
	 * correct and change the phone number if it is inaccessible.
	**/
	public static final class SuggestedActionCheckPhoneNumber extends SuggestedAction {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 648771563;

		/**
		 * Suggests the user to check whether authorization phone number is correct and change the phone number if it is inaccessible.
		**/
		public SuggestedActionCheckPhoneNumber() {}

		/**
		 * Suggests the user to check whether authorization phone number is correct and change the phone number if it is inaccessible.
		 *
		**/

		/**
		 * Suggests the user to check whether authorization phone number is correct and change the phone number if it is inaccessible.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SuggestedActionCheckPhoneNumber(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SuggestedActionCheckPhoneNumber.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SuggestedActionCheckPhoneNumber.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return SuggestedActionCheckPhoneNumber.CONSTRUCTOR;
		}
	}

	/**
	 * Suggests the user to view a hint about the meaning of one and two
	 * check marks on sent messages.
	**/
	public static final class SuggestedActionViewChecksHint extends SuggestedAction {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 891303239;

		/**
		 * Suggests the user to view a hint about the meaning of one and two check marks on sent messages.
		**/
		public SuggestedActionViewChecksHint() {}

		/**
		 * Suggests the user to view a hint about the meaning of one and two check marks on sent messages.
		 *
		**/

		/**
		 * Suggests the user to view a hint about the meaning of one and two check marks on sent messages.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SuggestedActionViewChecksHint(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SuggestedActionViewChecksHint.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SuggestedActionViewChecksHint.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return SuggestedActionViewChecksHint.CONSTRUCTOR;
		}
	}

	/**
	 * Suggests the user to convert specified supergroup to a broadcast
	 * group.
	**/
	public static final class SuggestedActionConvertToBroadcastGroup extends SuggestedAction {


		/**
		 * Supergroup identifier.
		**/
		public long supergroupId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -965071304;

		/**
		 * Suggests the user to convert specified supergroup to a broadcast group.
		**/
		public SuggestedActionConvertToBroadcastGroup() {}

		/**
		 * Suggests the user to convert specified supergroup to a broadcast group.
		 *
		 * @param supergroupId Supergroup identifier.
		**/
		public SuggestedActionConvertToBroadcastGroup(long supergroupId) {
			this.supergroupId = supergroupId;
		}

		/**
		 * Suggests the user to convert specified supergroup to a broadcast group.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SuggestedActionConvertToBroadcastGroup(DataInput input) throws IOException {
			this.supergroupId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SuggestedActionConvertToBroadcastGroup.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SuggestedActionConvertToBroadcastGroup.CONSTRUCTOR);
			output.writeLong(this.supergroupId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SuggestedActionConvertToBroadcastGroup suggestedActionConvertToBroadcastGroup = (SuggestedActionConvertToBroadcastGroup) o;
			if (this.supergroupId != suggestedActionConvertToBroadcastGroup.supergroupId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.supergroupId);
		}
	}

	/**
	 * Suggests the user to set a 2-step verification password to be able to
	 * log in again.
	**/
	public static final class SuggestedActionSetPassword extends SuggestedAction {


		/**
		 * The number of days to pass between consecutive authorizations if the user declines to set password; if 0, then the user is advised to set the password for security reasons.
		**/
		public int authorizationDelay;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1863613848;

		/**
		 * Suggests the user to set a 2-step verification password to be able to log in again.
		**/
		public SuggestedActionSetPassword() {}

		/**
		 * Suggests the user to set a 2-step verification password to be able to log in again.
		 *
		 * @param authorizationDelay The number of days to pass between consecutive authorizations if the user declines to set password; if 0, then the user is advised to set the password for security reasons.
		**/
		public SuggestedActionSetPassword(int authorizationDelay) {
			this.authorizationDelay = authorizationDelay;
		}

		/**
		 * Suggests the user to set a 2-step verification password to be able to log in again.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SuggestedActionSetPassword(DataInput input) throws IOException {
			this.authorizationDelay = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SuggestedActionSetPassword.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SuggestedActionSetPassword.CONSTRUCTOR);
			output.writeInt(this.authorizationDelay);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SuggestedActionSetPassword suggestedActionSetPassword = (SuggestedActionSetPassword) o;
			if (this.authorizationDelay != suggestedActionSetPassword.authorizationDelay) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.authorizationDelay);
		}
	}

	/**
	 * Suggests the user to upgrade the Premium subscription from monthly
	 * payments to annual payments.
	**/
	public static final class SuggestedActionUpgradePremium extends SuggestedAction {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1890220539;

		/**
		 * Suggests the user to upgrade the Premium subscription from monthly payments to annual payments.
		**/
		public SuggestedActionUpgradePremium() {}

		/**
		 * Suggests the user to upgrade the Premium subscription from monthly payments to annual payments.
		 *
		**/

		/**
		 * Suggests the user to upgrade the Premium subscription from monthly payments to annual payments.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SuggestedActionUpgradePremium(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SuggestedActionUpgradePremium.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SuggestedActionUpgradePremium.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return SuggestedActionUpgradePremium.CONSTRUCTOR;
		}
	}

	/**
	 * Suggests the user to subscribe to the Premium subscription with
	 * annual payments.
	**/
	public static final class SuggestedActionSubscribeToAnnualPremium extends SuggestedAction {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 373913787;

		/**
		 * Suggests the user to subscribe to the Premium subscription with annual payments.
		**/
		public SuggestedActionSubscribeToAnnualPremium() {}

		/**
		 * Suggests the user to subscribe to the Premium subscription with annual payments.
		 *
		**/

		/**
		 * Suggests the user to subscribe to the Premium subscription with annual payments.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SuggestedActionSubscribeToAnnualPremium(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SuggestedActionSubscribeToAnnualPremium.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SuggestedActionSubscribeToAnnualPremium.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return SuggestedActionSubscribeToAnnualPremium.CONSTRUCTOR;
		}
	}

	/**
	 * Represents a supergroup or channel with zero or more members
	 * (subscribers in the case of channels). From the point of view of the
	 * system, a channel is a special kind of a supergroup: only
	 * administrators can post and see the list of members, and posts from
	 * all administrators use the name and photo of the channel instead of
	 * individual names and profile photos. Unlike supergroups, channels can
	 * have an unlimited number of subscribers.
	**/
	public static final class Supergroup extends Object {


		/**
		 * Supergroup or channel identifier.
		**/
		public long id;

		/**
		 * Usernames of the supergroup or channel; may be null.
		**/
		public Usernames usernames;

		/**
		 * Point in time (Unix timestamp) when the current user joined, or the point in time when the supergroup or channel was created, in case the user is not a member.
		**/
		public int date;

		/**
		 * Status of the current user in the supergroup or channel; custom title will always be empty.
		**/
		public ChatMemberStatus status;

		/**
		 * Number of members in the supergroup or channel; 0 if unknown. Currently, it is guaranteed to be known only if the supergroup or channel was received through searchPublicChats, searchChatsNearby, getInactiveSupergroupChats, getSuitableDiscussionChats, getGroupsInCommon, getUserPrivacySettingRules, or in chatFolderInviteLinkInfo.missingChatIds.
		**/
		public int memberCount;

		/**
		 * True, if the channel has a discussion group, or the supergroup is the designated discussion group for a channel.
		**/
		public boolean hasLinkedChat;

		/**
		 * True, if the supergroup is connected to a location, i.e. the supergroup is a location-based supergroup.
		**/
		public boolean hasLocation;

		/**
		 * True, if messages sent to the channel need to contain information about the sender. This field is only applicable to channels.
		**/
		public boolean signMessages;

		/**
		 * True, if users need to join the supergroup before they can send messages. Always true for channels and non-discussion supergroups.
		**/
		public boolean joinToSendMessages;

		/**
		 * True, if all users directly joining the supergroup need to be approved by supergroup administrators. Always false for channels and supergroups without username, location, or a linked chat.
		**/
		public boolean joinByRequest;

		/**
		 * True, if the slow mode is enabled in the supergroup.
		**/
		public boolean isSlowModeEnabled;

		/**
		 * True, if the supergroup is a channel.
		**/
		public boolean isChannel;

		/**
		 * True, if the supergroup is a broadcast group, i.e. only administrators can send messages and there is no limit on the number of members.
		**/
		public boolean isBroadcastGroup;

		/**
		 * True, if the supergroup must be shown as a forum by default.
		**/
		public boolean isForum;

		/**
		 * True, if the supergroup or channel is verified.
		**/
		public boolean isVerified;

		/**
		 * If non-empty, contains a human-readable description of the reason why access to this supergroup or channel must be restricted.
		**/
		public String restrictionReason;

		/**
		 * True, if many users reported this supergroup or channel as a scam.
		**/
		public boolean isScam;

		/**
		 * True, if many users reported this supergroup or channel as a fake account.
		**/
		public boolean isFake;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2002240425;

		/**
		 * Represents a supergroup or channel with zero or more members (subscribers in the case of channels). From the point of view of the system, a channel is a special kind of a supergroup: only administrators can post and see the list of members, and posts from all administrators use the name and photo of the channel instead of individual names and profile photos. Unlike supergroups, channels can have an unlimited number of subscribers.
		**/
		public Supergroup() {}

		/**
		 * Represents a supergroup or channel with zero or more members (subscribers in the case of channels). From the point of view of the system, a channel is a special kind of a supergroup: only administrators can post and see the list of members, and posts from all administrators use the name and photo of the channel instead of individual names and profile photos. Unlike supergroups, channels can have an unlimited number of subscribers.
		 *
		 * @param id Supergroup or channel identifier.
		 * @param usernames Usernames of the supergroup or channel; may be null.
		 * @param date Point in time (Unix timestamp) when the current user joined, or the point in time when the supergroup or channel was created, in case the user is not a member.
		 * @param status Status of the current user in the supergroup or channel; custom title will always be empty.
		 * @param memberCount Number of members in the supergroup or channel; 0 if unknown. Currently, it is guaranteed to be known only if the supergroup or channel was received through searchPublicChats, searchChatsNearby, getInactiveSupergroupChats, getSuitableDiscussionChats, getGroupsInCommon, getUserPrivacySettingRules, or in chatFolderInviteLinkInfo.missingChatIds.
		 * @param hasLinkedChat True, if the channel has a discussion group, or the supergroup is the designated discussion group for a channel.
		 * @param hasLocation True, if the supergroup is connected to a location, i.e. the supergroup is a location-based supergroup.
		 * @param signMessages True, if messages sent to the channel need to contain information about the sender. This field is only applicable to channels.
		 * @param joinToSendMessages True, if users need to join the supergroup before they can send messages. Always true for channels and non-discussion supergroups.
		 * @param joinByRequest True, if all users directly joining the supergroup need to be approved by supergroup administrators. Always false for channels and supergroups without username, location, or a linked chat.
		 * @param isSlowModeEnabled True, if the slow mode is enabled in the supergroup.
		 * @param isChannel True, if the supergroup is a channel.
		 * @param isBroadcastGroup True, if the supergroup is a broadcast group, i.e. only administrators can send messages and there is no limit on the number of members.
		 * @param isForum True, if the supergroup must be shown as a forum by default.
		 * @param isVerified True, if the supergroup or channel is verified.
		 * @param restrictionReason If non-empty, contains a human-readable description of the reason why access to this supergroup or channel must be restricted.
		 * @param isScam True, if many users reported this supergroup or channel as a scam.
		 * @param isFake True, if many users reported this supergroup or channel as a fake account.
		**/
		public Supergroup(long id,
				Usernames usernames,
				int date,
				ChatMemberStatus status,
				int memberCount,
				boolean hasLinkedChat,
				boolean hasLocation,
				boolean signMessages,
				boolean joinToSendMessages,
				boolean joinByRequest,
				boolean isSlowModeEnabled,
				boolean isChannel,
				boolean isBroadcastGroup,
				boolean isForum,
				boolean isVerified,
				String restrictionReason,
				boolean isScam,
				boolean isFake) {
			this.id = id;
			this.usernames = usernames;
			this.date = date;
			this.status = status;
			this.memberCount = memberCount;
			this.hasLinkedChat = hasLinkedChat;
			this.hasLocation = hasLocation;
			this.signMessages = signMessages;
			this.joinToSendMessages = joinToSendMessages;
			this.joinByRequest = joinByRequest;
			this.isSlowModeEnabled = isSlowModeEnabled;
			this.isChannel = isChannel;
			this.isBroadcastGroup = isBroadcastGroup;
			this.isForum = isForum;
			this.isVerified = isVerified;
			this.restrictionReason = restrictionReason;
			this.isScam = isScam;
			this.isFake = isFake;
		}

		/**
		 * Represents a supergroup or channel with zero or more members (subscribers in the case of channels). From the point of view of the system, a channel is a special kind of a supergroup: only administrators can post and see the list of members, and posts from all administrators use the name and photo of the channel instead of individual names and profile photos. Unlike supergroups, channels can have an unlimited number of subscribers.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public Supergroup(DataInput input) throws IOException {
			this.id = input.readLong();
			if (input.readBoolean()) {
				if (Usernames.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.usernames = new Usernames(input);
			}
			this.date = input.readInt();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ChatMemberStatusCreator.CONSTRUCTOR: this.status = new ChatMemberStatusCreator(input); break;
					case ChatMemberStatusAdministrator.CONSTRUCTOR: this.status = new ChatMemberStatusAdministrator(input); break;
					case ChatMemberStatusMember.CONSTRUCTOR: this.status = new ChatMemberStatusMember(input); break;
					case ChatMemberStatusRestricted.CONSTRUCTOR: this.status = new ChatMemberStatusRestricted(input); break;
					case ChatMemberStatusLeft.CONSTRUCTOR: this.status = new ChatMemberStatusLeft(input); break;
					case ChatMemberStatusBanned.CONSTRUCTOR: this.status = new ChatMemberStatusBanned(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.memberCount = input.readInt();
			this.hasLinkedChat = input.readBoolean();
			this.hasLocation = input.readBoolean();
			this.signMessages = input.readBoolean();
			this.joinToSendMessages = input.readBoolean();
			this.joinByRequest = input.readBoolean();
			this.isSlowModeEnabled = input.readBoolean();
			this.isChannel = input.readBoolean();
			this.isBroadcastGroup = input.readBoolean();
			this.isForum = input.readBoolean();
			this.isVerified = input.readBoolean();
			if (input.readBoolean()) {
				byte[] restrictionReasonTmp = new byte[input.readInt()];
				input.readFully(restrictionReasonTmp);
				this.restrictionReason = new String(restrictionReasonTmp, StandardCharsets.UTF_8);
			}
			this.isScam = input.readBoolean();
			this.isFake = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return Supergroup.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(Supergroup.CONSTRUCTOR);
			output.writeLong(this.id);
			if (this.usernames == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.usernames.serialize(output);
			}
			output.writeInt(this.date);
			if (this.status == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.status.serialize(output);
			}
			output.writeInt(this.memberCount);
			output.writeBoolean(this.hasLinkedChat);
			output.writeBoolean(this.hasLocation);
			output.writeBoolean(this.signMessages);
			output.writeBoolean(this.joinToSendMessages);
			output.writeBoolean(this.joinByRequest);
			output.writeBoolean(this.isSlowModeEnabled);
			output.writeBoolean(this.isChannel);
			output.writeBoolean(this.isBroadcastGroup);
			output.writeBoolean(this.isForum);
			output.writeBoolean(this.isVerified);
			if (this.restrictionReason == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] restrictionReasonTmp = this.restrictionReason.getBytes(StandardCharsets.UTF_8);
				output.writeInt(restrictionReasonTmp.length);
				output.write(restrictionReasonTmp);
			}
			output.writeBoolean(this.isScam);
			output.writeBoolean(this.isFake);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			Supergroup supergroup = (Supergroup) o;
			if (this.id != supergroup.id) {
				return false;
			}
			if (!Objects.equals(this.usernames, supergroup.usernames)) {
				return false;
			}
			if (this.date != supergroup.date) {
				return false;
			}
			if (!Objects.equals(this.status, supergroup.status)) {
				return false;
			}
			if (this.memberCount != supergroup.memberCount) {
				return false;
			}
			if (this.hasLinkedChat != supergroup.hasLinkedChat) {
				return false;
			}
			if (this.hasLocation != supergroup.hasLocation) {
				return false;
			}
			if (this.signMessages != supergroup.signMessages) {
				return false;
			}
			if (this.joinToSendMessages != supergroup.joinToSendMessages) {
				return false;
			}
			if (this.joinByRequest != supergroup.joinByRequest) {
				return false;
			}
			if (this.isSlowModeEnabled != supergroup.isSlowModeEnabled) {
				return false;
			}
			if (this.isChannel != supergroup.isChannel) {
				return false;
			}
			if (this.isBroadcastGroup != supergroup.isBroadcastGroup) {
				return false;
			}
			if (this.isForum != supergroup.isForum) {
				return false;
			}
			if (this.isVerified != supergroup.isVerified) {
				return false;
			}
			if (this.restrictionReason != supergroup.restrictionReason) {
				return false;
			}
			if (this.isScam != supergroup.isScam) {
				return false;
			}
			if (this.isFake != supergroup.isFake) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.id);
			result = result * 31 + (this.usernames == null ? 0 : this.usernames.hashCode());
			result = result * 31 + (this.status == null ? 0 : this.status.hashCode());
			result = result * 31 + (this.restrictionReason == null ? 0 : this.restrictionReason.hashCode());
			return result;
		}
	}

	/**
	 * Contains full information about a supergroup or channel.
	**/
	public static final class SupergroupFullInfo extends Object {


		/**
		 * Chat photo; may be null if empty or unknown. If non-null, then it is the same photo as in chat.photo.
		**/
		public ChatPhoto photo;

		/**
		 * Supergroup or channel description.
		**/
		public String description;

		/**
		 * Number of members in the supergroup or channel; 0 if unknown.
		**/
		public int memberCount;

		/**
		 * Number of privileged users in the supergroup or channel; 0 if unknown.
		**/
		public int administratorCount;

		/**
		 * Number of restricted users in the supergroup; 0 if unknown.
		**/
		public int restrictedCount;

		/**
		 * Number of users banned from chat; 0 if unknown.
		**/
		public int bannedCount;

		/**
		 * Chat identifier of a discussion group for the channel, or a channel, for which the supergroup is the designated discussion group; 0 if none or unknown.
		**/
		public long linkedChatId;

		/**
		 * Delay between consecutive sent messages for non-administrator supergroup members, in seconds.
		**/
		public int slowModeDelay;

		/**
		 * Time left before next message can be sent in the supergroup, in seconds. An updateSupergroupFullInfo update is not triggered when value of this field changes, but both new and old values are non-zero.
		**/
		public double slowModeDelayExpiresIn;

		/**
		 * True, if members of the chat can be retrieved via getSupergroupMembers or searchChatMembers.
		**/
		public boolean canGetMembers;

		/**
		 * True, if non-administrators can receive only administrators and bots using getSupergroupMembers or searchChatMembers.
		**/
		public boolean hasHiddenMembers;

		/**
		 * True, if non-administrators and non-bots can be hidden in responses to getSupergroupMembers and searchChatMembers for non-administrators.
		**/
		public boolean canHideMembers;

		/**
		 * True, if the chat username can be changed.
		**/
		public boolean canSetUsername;

		/**
		 * True, if the supergroup sticker set can be changed.
		**/
		public boolean canSetStickerSet;

		/**
		 * True, if the supergroup location can be changed.
		**/
		public boolean canSetLocation;

		/**
		 * True, if the supergroup or channel statistics are available.
		**/
		public boolean canGetStatistics;

		/**
		 * True, if aggressive anti-spam checks can be enabled or disabled in the supergroup.
		**/
		public boolean canToggleAggressiveAntiSpam;

		/**
		 * True, if new chat members will have access to old messages. In public, discussion, of forum groups and all channels, old messages are always available, so this option affects only private non-forum supergroups without a linked chat. The value of this field is only available to chat administrators.
		**/
		public boolean isAllHistoryAvailable;

		/**
		 * True, if aggressive anti-spam checks are enabled in the supergroup. The value of this field is only available to chat administrators.
		**/
		public boolean hasAggressiveAntiSpamEnabled;

		/**
		 * Identifier of the supergroup sticker set; 0 if none.
		**/
		public long stickerSetId;

		/**
		 * Location to which the supergroup is connected; may be null.
		**/
		public ChatLocation location;

		/**
		 * Primary invite link for the chat; may be null. For chat administrators with canInviteUsers right only.
		**/
		public ChatInviteLink inviteLink;

		/**
		 * List of commands of bots in the group.
		**/
		public BotCommands[] botCommands;

		/**
		 * Identifier of the basic group from which supergroup was upgraded; 0 if none.
		**/
		public long upgradedFromBasicGroupId;

		/**
		 * Identifier of the last message in the basic group from which supergroup was upgraded; 0 if none.
		**/
		public long upgradedFromMaxMessageId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1632629458;

		/**
		 * Contains full information about a supergroup or channel.
		**/
		public SupergroupFullInfo() {}

		/**
		 * Contains full information about a supergroup or channel.
		 *
		 * @param photo Chat photo; may be null if empty or unknown. If non-null, then it is the same photo as in chat.photo.
		 * @param description Supergroup or channel description.
		 * @param memberCount Number of members in the supergroup or channel; 0 if unknown.
		 * @param administratorCount Number of privileged users in the supergroup or channel; 0 if unknown.
		 * @param restrictedCount Number of restricted users in the supergroup; 0 if unknown.
		 * @param bannedCount Number of users banned from chat; 0 if unknown.
		 * @param linkedChatId Chat identifier of a discussion group for the channel, or a channel, for which the supergroup is the designated discussion group; 0 if none or unknown.
		 * @param slowModeDelay Delay between consecutive sent messages for non-administrator supergroup members, in seconds.
		 * @param slowModeDelayExpiresIn Time left before next message can be sent in the supergroup, in seconds. An updateSupergroupFullInfo update is not triggered when value of this field changes, but both new and old values are non-zero.
		 * @param canGetMembers True, if members of the chat can be retrieved via getSupergroupMembers or searchChatMembers.
		 * @param hasHiddenMembers True, if non-administrators can receive only administrators and bots using getSupergroupMembers or searchChatMembers.
		 * @param canHideMembers True, if non-administrators and non-bots can be hidden in responses to getSupergroupMembers and searchChatMembers for non-administrators.
		 * @param canSetUsername True, if the chat username can be changed.
		 * @param canSetStickerSet True, if the supergroup sticker set can be changed.
		 * @param canSetLocation True, if the supergroup location can be changed.
		 * @param canGetStatistics True, if the supergroup or channel statistics are available.
		 * @param canToggleAggressiveAntiSpam True, if aggressive anti-spam checks can be enabled or disabled in the supergroup.
		 * @param isAllHistoryAvailable True, if new chat members will have access to old messages. In public, discussion, of forum groups and all channels, old messages are always available, so this option affects only private non-forum supergroups without a linked chat. The value of this field is only available to chat administrators.
		 * @param hasAggressiveAntiSpamEnabled True, if aggressive anti-spam checks are enabled in the supergroup. The value of this field is only available to chat administrators.
		 * @param stickerSetId Identifier of the supergroup sticker set; 0 if none.
		 * @param location Location to which the supergroup is connected; may be null.
		 * @param inviteLink Primary invite link for the chat; may be null. For chat administrators with canInviteUsers right only.
		 * @param botCommands List of commands of bots in the group.
		 * @param upgradedFromBasicGroupId Identifier of the basic group from which supergroup was upgraded; 0 if none.
		 * @param upgradedFromMaxMessageId Identifier of the last message in the basic group from which supergroup was upgraded; 0 if none.
		**/
		public SupergroupFullInfo(ChatPhoto photo,
				String description,
				int memberCount,
				int administratorCount,
				int restrictedCount,
				int bannedCount,
				long linkedChatId,
				int slowModeDelay,
				double slowModeDelayExpiresIn,
				boolean canGetMembers,
				boolean hasHiddenMembers,
				boolean canHideMembers,
				boolean canSetUsername,
				boolean canSetStickerSet,
				boolean canSetLocation,
				boolean canGetStatistics,
				boolean canToggleAggressiveAntiSpam,
				boolean isAllHistoryAvailable,
				boolean hasAggressiveAntiSpamEnabled,
				long stickerSetId,
				ChatLocation location,
				ChatInviteLink inviteLink,
				BotCommands[] botCommands,
				long upgradedFromBasicGroupId,
				long upgradedFromMaxMessageId) {
			this.photo = photo;
			this.description = description;
			this.memberCount = memberCount;
			this.administratorCount = administratorCount;
			this.restrictedCount = restrictedCount;
			this.bannedCount = bannedCount;
			this.linkedChatId = linkedChatId;
			this.slowModeDelay = slowModeDelay;
			this.slowModeDelayExpiresIn = slowModeDelayExpiresIn;
			this.canGetMembers = canGetMembers;
			this.hasHiddenMembers = hasHiddenMembers;
			this.canHideMembers = canHideMembers;
			this.canSetUsername = canSetUsername;
			this.canSetStickerSet = canSetStickerSet;
			this.canSetLocation = canSetLocation;
			this.canGetStatistics = canGetStatistics;
			this.canToggleAggressiveAntiSpam = canToggleAggressiveAntiSpam;
			this.isAllHistoryAvailable = isAllHistoryAvailable;
			this.hasAggressiveAntiSpamEnabled = hasAggressiveAntiSpamEnabled;
			this.stickerSetId = stickerSetId;
			this.location = location;
			this.inviteLink = inviteLink;
			this.botCommands = botCommands;
			this.upgradedFromBasicGroupId = upgradedFromBasicGroupId;
			this.upgradedFromMaxMessageId = upgradedFromMaxMessageId;
		}

		/**
		 * Contains full information about a supergroup or channel.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SupergroupFullInfo(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (ChatPhoto.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.photo = new ChatPhoto(input);
			}
			if (input.readBoolean()) {
				byte[] descriptionTmp = new byte[input.readInt()];
				input.readFully(descriptionTmp);
				this.description = new String(descriptionTmp, StandardCharsets.UTF_8);
			}
			this.memberCount = input.readInt();
			this.administratorCount = input.readInt();
			this.restrictedCount = input.readInt();
			this.bannedCount = input.readInt();
			this.linkedChatId = input.readLong();
			this.slowModeDelay = input.readInt();
			this.slowModeDelayExpiresIn = input.readDouble();
			this.canGetMembers = input.readBoolean();
			this.hasHiddenMembers = input.readBoolean();
			this.canHideMembers = input.readBoolean();
			this.canSetUsername = input.readBoolean();
			this.canSetStickerSet = input.readBoolean();
			this.canSetLocation = input.readBoolean();
			this.canGetStatistics = input.readBoolean();
			this.canToggleAggressiveAntiSpam = input.readBoolean();
			this.isAllHistoryAvailable = input.readBoolean();
			this.hasAggressiveAntiSpamEnabled = input.readBoolean();
			this.stickerSetId = input.readLong();
			if (input.readBoolean()) {
				if (ChatLocation.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.location = new ChatLocation(input);
			}
			if (input.readBoolean()) {
				if (ChatInviteLink.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.inviteLink = new ChatInviteLink(input);
			}
			if (input.readBoolean()) {
				this.botCommands = new BotCommands[input.readInt()];
				for (int i = 0; i < this.botCommands.length; i++) {
					if (BotCommands.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.botCommands[i] = new BotCommands(input);
				}
			}
			this.upgradedFromBasicGroupId = input.readLong();
			this.upgradedFromMaxMessageId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SupergroupFullInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SupergroupFullInfo.CONSTRUCTOR);
			if (this.photo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.photo.serialize(output);
			}
			if (this.description == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] descriptionTmp = this.description.getBytes(StandardCharsets.UTF_8);
				output.writeInt(descriptionTmp.length);
				output.write(descriptionTmp);
			}
			output.writeInt(this.memberCount);
			output.writeInt(this.administratorCount);
			output.writeInt(this.restrictedCount);
			output.writeInt(this.bannedCount);
			output.writeLong(this.linkedChatId);
			output.writeInt(this.slowModeDelay);
			output.writeDouble(this.slowModeDelayExpiresIn);
			output.writeBoolean(this.canGetMembers);
			output.writeBoolean(this.hasHiddenMembers);
			output.writeBoolean(this.canHideMembers);
			output.writeBoolean(this.canSetUsername);
			output.writeBoolean(this.canSetStickerSet);
			output.writeBoolean(this.canSetLocation);
			output.writeBoolean(this.canGetStatistics);
			output.writeBoolean(this.canToggleAggressiveAntiSpam);
			output.writeBoolean(this.isAllHistoryAvailable);
			output.writeBoolean(this.hasAggressiveAntiSpamEnabled);
			output.writeLong(this.stickerSetId);
			if (this.location == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.location.serialize(output);
			}
			if (this.inviteLink == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.inviteLink.serialize(output);
			}
			if (this.botCommands == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.botCommands.length);
				for (int i = 0; i < this.botCommands.length; i++) {
					this.botCommands[i].serialize(output);
				}
			}
			output.writeLong(this.upgradedFromBasicGroupId);
			output.writeLong(this.upgradedFromMaxMessageId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SupergroupFullInfo supergroupFullInfo = (SupergroupFullInfo) o;
			if (!Objects.equals(this.photo, supergroupFullInfo.photo)) {
				return false;
			}
			if (this.description != supergroupFullInfo.description) {
				return false;
			}
			if (this.memberCount != supergroupFullInfo.memberCount) {
				return false;
			}
			if (this.administratorCount != supergroupFullInfo.administratorCount) {
				return false;
			}
			if (this.restrictedCount != supergroupFullInfo.restrictedCount) {
				return false;
			}
			if (this.bannedCount != supergroupFullInfo.bannedCount) {
				return false;
			}
			if (this.linkedChatId != supergroupFullInfo.linkedChatId) {
				return false;
			}
			if (this.slowModeDelay != supergroupFullInfo.slowModeDelay) {
				return false;
			}
			if (this.slowModeDelayExpiresIn != supergroupFullInfo.slowModeDelayExpiresIn) {
				return false;
			}
			if (this.canGetMembers != supergroupFullInfo.canGetMembers) {
				return false;
			}
			if (this.hasHiddenMembers != supergroupFullInfo.hasHiddenMembers) {
				return false;
			}
			if (this.canHideMembers != supergroupFullInfo.canHideMembers) {
				return false;
			}
			if (this.canSetUsername != supergroupFullInfo.canSetUsername) {
				return false;
			}
			if (this.canSetStickerSet != supergroupFullInfo.canSetStickerSet) {
				return false;
			}
			if (this.canSetLocation != supergroupFullInfo.canSetLocation) {
				return false;
			}
			if (this.canGetStatistics != supergroupFullInfo.canGetStatistics) {
				return false;
			}
			if (this.canToggleAggressiveAntiSpam != supergroupFullInfo.canToggleAggressiveAntiSpam) {
				return false;
			}
			if (this.isAllHistoryAvailable != supergroupFullInfo.isAllHistoryAvailable) {
				return false;
			}
			if (this.hasAggressiveAntiSpamEnabled != supergroupFullInfo.hasAggressiveAntiSpamEnabled) {
				return false;
			}
			if (this.stickerSetId != supergroupFullInfo.stickerSetId) {
				return false;
			}
			if (!Objects.equals(this.location, supergroupFullInfo.location)) {
				return false;
			}
			if (!Objects.equals(this.inviteLink, supergroupFullInfo.inviteLink)) {
				return false;
			}
			if (!Arrays.equals(this.botCommands, supergroupFullInfo.botCommands)) {
				return false;
			}
			if (this.upgradedFromBasicGroupId != supergroupFullInfo.upgradedFromBasicGroupId) {
				return false;
			}
			if (this.upgradedFromMaxMessageId != supergroupFullInfo.upgradedFromMaxMessageId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.memberCount);
			result = result * 31 + (this.photo == null ? 0 : this.photo.hashCode());
			result = result * 31 + (this.description == null ? 0 : this.description.hashCode());
			result = result * 31 + (this.location == null ? 0 : this.location.hashCode());
			result = result * 31 + (this.inviteLink == null ? 0 : this.inviteLink.hashCode());
			result = result * 31 + (Arrays.hashCode(this.botCommands));
			return result;
		}
	}

	/**
	 * Returns recently active users in reverse chronological order.
	**/
	public static final class SupergroupMembersFilterRecent extends SupergroupMembersFilter {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1178199509;

		/**
		 * Returns recently active users in reverse chronological order.
		**/
		public SupergroupMembersFilterRecent() {}

		/**
		 * Returns recently active users in reverse chronological order.
		 *
		**/

		/**
		 * Returns recently active users in reverse chronological order.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SupergroupMembersFilterRecent(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SupergroupMembersFilterRecent.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SupergroupMembersFilterRecent.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return SupergroupMembersFilterRecent.CONSTRUCTOR;
		}
	}

	/**
	 * Returns contacts of the user, which are members of the supergroup or
	 * channel.
	**/
	public static final class SupergroupMembersFilterContacts extends SupergroupMembersFilter {


		/**
		 * Query to search for.
		**/
		public String query;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1282910856;

		/**
		 * Returns contacts of the user, which are members of the supergroup or channel.
		**/
		public SupergroupMembersFilterContacts() {}

		/**
		 * Returns contacts of the user, which are members of the supergroup or channel.
		 *
		 * @param query Query to search for.
		**/
		public SupergroupMembersFilterContacts(String query) {
			this.query = query;
		}

		/**
		 * Returns contacts of the user, which are members of the supergroup or channel.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SupergroupMembersFilterContacts(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] queryTmp = new byte[input.readInt()];
				input.readFully(queryTmp);
				this.query = new String(queryTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SupergroupMembersFilterContacts.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SupergroupMembersFilterContacts.CONSTRUCTOR);
			if (this.query == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] queryTmp = this.query.getBytes(StandardCharsets.UTF_8);
				output.writeInt(queryTmp.length);
				output.write(queryTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SupergroupMembersFilterContacts supergroupMembersFilterContacts = (SupergroupMembersFilterContacts) o;
			if (this.query != supergroupMembersFilterContacts.query) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.query == null ? 0 : this.query.hashCode();
		}
	}

	/**
	 * Returns the owner and administrators.
	**/
	public static final class SupergroupMembersFilterAdministrators extends SupergroupMembersFilter {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2097380265;

		/**
		 * Returns the owner and administrators.
		**/
		public SupergroupMembersFilterAdministrators() {}

		/**
		 * Returns the owner and administrators.
		 *
		**/

		/**
		 * Returns the owner and administrators.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SupergroupMembersFilterAdministrators(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SupergroupMembersFilterAdministrators.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SupergroupMembersFilterAdministrators.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return SupergroupMembersFilterAdministrators.CONSTRUCTOR;
		}
	}

	/**
	 * Used to search for supergroup or channel members via a (string) query.
	**/
	public static final class SupergroupMembersFilterSearch extends SupergroupMembersFilter {


		/**
		 * Query to search for.
		**/
		public String query;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1696358469;

		/**
		 * Used to search for supergroup or channel members via a (string) query.
		**/
		public SupergroupMembersFilterSearch() {}

		/**
		 * Used to search for supergroup or channel members via a (string) query.
		 *
		 * @param query Query to search for.
		**/
		public SupergroupMembersFilterSearch(String query) {
			this.query = query;
		}

		/**
		 * Used to search for supergroup or channel members via a (string) query.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SupergroupMembersFilterSearch(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] queryTmp = new byte[input.readInt()];
				input.readFully(queryTmp);
				this.query = new String(queryTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SupergroupMembersFilterSearch.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SupergroupMembersFilterSearch.CONSTRUCTOR);
			if (this.query == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] queryTmp = this.query.getBytes(StandardCharsets.UTF_8);
				output.writeInt(queryTmp.length);
				output.write(queryTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SupergroupMembersFilterSearch supergroupMembersFilterSearch = (SupergroupMembersFilterSearch) o;
			if (this.query != supergroupMembersFilterSearch.query) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.query == null ? 0 : this.query.hashCode();
		}
	}

	/**
	 * Returns restricted supergroup members; can be used only by
	 * administrators.
	**/
	public static final class SupergroupMembersFilterRestricted extends SupergroupMembersFilter {


		/**
		 * Query to search for.
		**/
		public String query;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1107800034;

		/**
		 * Returns restricted supergroup members; can be used only by administrators.
		**/
		public SupergroupMembersFilterRestricted() {}

		/**
		 * Returns restricted supergroup members; can be used only by administrators.
		 *
		 * @param query Query to search for.
		**/
		public SupergroupMembersFilterRestricted(String query) {
			this.query = query;
		}

		/**
		 * Returns restricted supergroup members; can be used only by administrators.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SupergroupMembersFilterRestricted(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] queryTmp = new byte[input.readInt()];
				input.readFully(queryTmp);
				this.query = new String(queryTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SupergroupMembersFilterRestricted.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SupergroupMembersFilterRestricted.CONSTRUCTOR);
			if (this.query == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] queryTmp = this.query.getBytes(StandardCharsets.UTF_8);
				output.writeInt(queryTmp.length);
				output.write(queryTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SupergroupMembersFilterRestricted supergroupMembersFilterRestricted = (SupergroupMembersFilterRestricted) o;
			if (this.query != supergroupMembersFilterRestricted.query) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.query == null ? 0 : this.query.hashCode();
		}
	}

	/**
	 * Returns users banned from the supergroup or channel; can be used only
	 * by administrators.
	**/
	public static final class SupergroupMembersFilterBanned extends SupergroupMembersFilter {


		/**
		 * Query to search for.
		**/
		public String query;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1210621683;

		/**
		 * Returns users banned from the supergroup or channel; can be used only by administrators.
		**/
		public SupergroupMembersFilterBanned() {}

		/**
		 * Returns users banned from the supergroup or channel; can be used only by administrators.
		 *
		 * @param query Query to search for.
		**/
		public SupergroupMembersFilterBanned(String query) {
			this.query = query;
		}

		/**
		 * Returns users banned from the supergroup or channel; can be used only by administrators.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SupergroupMembersFilterBanned(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] queryTmp = new byte[input.readInt()];
				input.readFully(queryTmp);
				this.query = new String(queryTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SupergroupMembersFilterBanned.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SupergroupMembersFilterBanned.CONSTRUCTOR);
			if (this.query == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] queryTmp = this.query.getBytes(StandardCharsets.UTF_8);
				output.writeInt(queryTmp.length);
				output.write(queryTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SupergroupMembersFilterBanned supergroupMembersFilterBanned = (SupergroupMembersFilterBanned) o;
			if (this.query != supergroupMembersFilterBanned.query) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.query == null ? 0 : this.query.hashCode();
		}
	}

	/**
	 * Returns users which can be mentioned in the supergroup.
	**/
	public static final class SupergroupMembersFilterMention extends SupergroupMembersFilter {


		/**
		 * Query to search for.
		**/
		public String query;

		/**
		 * If non-zero, the identifier of the current message thread.
		**/
		public long messageThreadId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 947915036;

		/**
		 * Returns users which can be mentioned in the supergroup.
		**/
		public SupergroupMembersFilterMention() {}

		/**
		 * Returns users which can be mentioned in the supergroup.
		 *
		 * @param query Query to search for.
		 * @param messageThreadId If non-zero, the identifier of the current message thread.
		**/
		public SupergroupMembersFilterMention(String query, long messageThreadId) {
			this.query = query;
			this.messageThreadId = messageThreadId;
		}

		/**
		 * Returns users which can be mentioned in the supergroup.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SupergroupMembersFilterMention(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] queryTmp = new byte[input.readInt()];
				input.readFully(queryTmp);
				this.query = new String(queryTmp, StandardCharsets.UTF_8);
			}
			this.messageThreadId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SupergroupMembersFilterMention.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SupergroupMembersFilterMention.CONSTRUCTOR);
			if (this.query == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] queryTmp = this.query.getBytes(StandardCharsets.UTF_8);
				output.writeInt(queryTmp.length);
				output.write(queryTmp);
			}
			output.writeLong(this.messageThreadId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SupergroupMembersFilterMention supergroupMembersFilterMention = (SupergroupMembersFilterMention) o;
			if (this.query != supergroupMembersFilterMention.query) {
				return false;
			}
			if (this.messageThreadId != supergroupMembersFilterMention.messageThreadId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.messageThreadId);
			result = result * 31 + (this.query == null ? 0 : this.query.hashCode());
			return result;
		}
	}

	/**
	 * Returns bot members of the supergroup or channel.
	**/
	public static final class SupergroupMembersFilterBots extends SupergroupMembersFilter {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 492138918;

		/**
		 * Returns bot members of the supergroup or channel.
		**/
		public SupergroupMembersFilterBots() {}

		/**
		 * Returns bot members of the supergroup or channel.
		 *
		**/

		/**
		 * Returns bot members of the supergroup or channel.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SupergroupMembersFilterBots(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SupergroupMembersFilterBots.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SupergroupMembersFilterBots.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return SupergroupMembersFilterBots.CONSTRUCTOR;
		}
	}

	/**
	 * Represents a URL linking to an internal Telegram entity.
	**/
	public static final class TMeUrl extends Object {


		/**
		 * URL.
		**/
		public String url;

		/**
		 * Type of the URL.
		**/
		public TMeUrlType type;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1140786622;

		/**
		 * Represents a URL linking to an internal Telegram entity.
		**/
		public TMeUrl() {}

		/**
		 * Represents a URL linking to an internal Telegram entity.
		 *
		 * @param url URL.
		 * @param type Type of the URL.
		**/
		public TMeUrl(String url, TMeUrlType type) {
			this.url = url;
			this.type = type;
		}

		/**
		 * Represents a URL linking to an internal Telegram entity.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TMeUrl(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] urlTmp = new byte[input.readInt()];
				input.readFully(urlTmp);
				this.url = new String(urlTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case TMeUrlTypeUser.CONSTRUCTOR: this.type = new TMeUrlTypeUser(input); break;
					case TMeUrlTypeSupergroup.CONSTRUCTOR: this.type = new TMeUrlTypeSupergroup(input); break;
					case TMeUrlTypeChatInvite.CONSTRUCTOR: this.type = new TMeUrlTypeChatInvite(input); break;
					case TMeUrlTypeStickerSet.CONSTRUCTOR: this.type = new TMeUrlTypeStickerSet(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TMeUrl.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TMeUrl.CONSTRUCTOR);
			if (this.url == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] urlTmp = this.url.getBytes(StandardCharsets.UTF_8);
				output.writeInt(urlTmp.length);
				output.write(urlTmp);
			}
			if (this.type == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.type.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			TMeUrl tMeUrl = (TMeUrl) o;
			if (this.url != tMeUrl.url) {
				return false;
			}
			if (!Objects.equals(this.type, tMeUrl.type)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.url == null ? 0 : this.url.hashCode();
			result = result * 31 + (this.type == null ? 0 : this.type.hashCode());
			return result;
		}
	}

	/**
	 * A URL linking to a user.
	**/
	public static final class TMeUrlTypeUser extends TMeUrlType {


		/**
		 * Identifier of the user.
		**/
		public long userId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 125336602;

		/**
		 * A URL linking to a user.
		**/
		public TMeUrlTypeUser() {}

		/**
		 * A URL linking to a user.
		 *
		 * @param userId Identifier of the user.
		**/
		public TMeUrlTypeUser(long userId) {
			this.userId = userId;
		}

		/**
		 * A URL linking to a user.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TMeUrlTypeUser(DataInput input) throws IOException {
			this.userId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TMeUrlTypeUser.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TMeUrlTypeUser.CONSTRUCTOR);
			output.writeLong(this.userId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			TMeUrlTypeUser tMeUrlTypeUser = (TMeUrlTypeUser) o;
			if (this.userId != tMeUrlTypeUser.userId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.userId);
		}
	}

	/**
	 * A URL linking to a public supergroup or channel.
	**/
	public static final class TMeUrlTypeSupergroup extends TMeUrlType {


		/**
		 * Identifier of the supergroup or channel.
		**/
		public long supergroupId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1353369944;

		/**
		 * A URL linking to a public supergroup or channel.
		**/
		public TMeUrlTypeSupergroup() {}

		/**
		 * A URL linking to a public supergroup or channel.
		 *
		 * @param supergroupId Identifier of the supergroup or channel.
		**/
		public TMeUrlTypeSupergroup(long supergroupId) {
			this.supergroupId = supergroupId;
		}

		/**
		 * A URL linking to a public supergroup or channel.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TMeUrlTypeSupergroup(DataInput input) throws IOException {
			this.supergroupId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TMeUrlTypeSupergroup.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TMeUrlTypeSupergroup.CONSTRUCTOR);
			output.writeLong(this.supergroupId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			TMeUrlTypeSupergroup tMeUrlTypeSupergroup = (TMeUrlTypeSupergroup) o;
			if (this.supergroupId != tMeUrlTypeSupergroup.supergroupId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.supergroupId);
		}
	}

	/**
	 * A chat invite link.
	**/
	public static final class TMeUrlTypeChatInvite extends TMeUrlType {


		/**
		 * Information about the chat invite link.
		**/
		public ChatInviteLinkInfo info;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 313907785;

		/**
		 * A chat invite link.
		**/
		public TMeUrlTypeChatInvite() {}

		/**
		 * A chat invite link.
		 *
		 * @param info Information about the chat invite link.
		**/
		public TMeUrlTypeChatInvite(ChatInviteLinkInfo info) {
			this.info = info;
		}

		/**
		 * A chat invite link.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TMeUrlTypeChatInvite(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (ChatInviteLinkInfo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.info = new ChatInviteLinkInfo(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TMeUrlTypeChatInvite.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TMeUrlTypeChatInvite.CONSTRUCTOR);
			if (this.info == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.info.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			TMeUrlTypeChatInvite tMeUrlTypeChatInvite = (TMeUrlTypeChatInvite) o;
			if (!Objects.equals(this.info, tMeUrlTypeChatInvite.info)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.info == null ? 0 : this.info.hashCode();
		}
	}

	/**
	 * A URL linking to a sticker set.
	**/
	public static final class TMeUrlTypeStickerSet extends TMeUrlType {


		/**
		 * Identifier of the sticker set.
		**/
		public long stickerSetId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1602473196;

		/**
		 * A URL linking to a sticker set.
		**/
		public TMeUrlTypeStickerSet() {}

		/**
		 * A URL linking to a sticker set.
		 *
		 * @param stickerSetId Identifier of the sticker set.
		**/
		public TMeUrlTypeStickerSet(long stickerSetId) {
			this.stickerSetId = stickerSetId;
		}

		/**
		 * A URL linking to a sticker set.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TMeUrlTypeStickerSet(DataInput input) throws IOException {
			this.stickerSetId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TMeUrlTypeStickerSet.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TMeUrlTypeStickerSet.CONSTRUCTOR);
			output.writeLong(this.stickerSetId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			TMeUrlTypeStickerSet tMeUrlTypeStickerSet = (TMeUrlTypeStickerSet) o;
			if (this.stickerSetId != tMeUrlTypeStickerSet.stickerSetId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.stickerSetId);
		}
	}

	/**
	 * Contains a list of t.me URLs.
	**/
	public static final class TMeUrls extends Object {


		/**
		 * List of URLs.
		**/
		public TMeUrl[] urls;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1130595098;

		/**
		 * Contains a list of t.me URLs.
		**/
		public TMeUrls() {}

		/**
		 * Contains a list of t.me URLs.
		 *
		 * @param urls List of URLs.
		**/
		public TMeUrls(TMeUrl[] urls) {
			this.urls = urls;
		}

		/**
		 * Contains a list of t.me URLs.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TMeUrls(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.urls = new TMeUrl[input.readInt()];
				for (int i = 0; i < this.urls.length; i++) {
					if (TMeUrl.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.urls[i] = new TMeUrl(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TMeUrls.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TMeUrls.CONSTRUCTOR);
			if (this.urls == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.urls.length);
				for (int i = 0; i < this.urls.length; i++) {
					this.urls[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			TMeUrls tMeUrls = (TMeUrls) o;
			if (!Arrays.equals(this.urls, tMeUrls.urls)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.urls);
		}
	}

	/**
	 * The currently opened chat needs to be kept.
	**/
	public static final class TargetChatCurrent extends TargetChat {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -416689904;

		/**
		 * The currently opened chat needs to be kept.
		**/
		public TargetChatCurrent() {}

		/**
		 * The currently opened chat needs to be kept.
		 *
		**/

		/**
		 * The currently opened chat needs to be kept.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TargetChatCurrent(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TargetChatCurrent.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TargetChatCurrent.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return TargetChatCurrent.CONSTRUCTOR;
		}
	}

	/**
	 * The chat needs to be chosen by the user among chats of the specified
	 * types.
	**/
	public static final class TargetChatChosen extends TargetChat {


		/**
		 * True, if private chats with ordinary users are allowed.
		**/
		public boolean allowUserChats;

		/**
		 * True, if private chats with other bots are allowed.
		**/
		public boolean allowBotChats;

		/**
		 * True, if basic group and supergroup chats are allowed.
		**/
		public boolean allowGroupChats;

		/**
		 * True, if channel chats are allowed.
		**/
		public boolean allowChannelChats;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -307442990;

		/**
		 * The chat needs to be chosen by the user among chats of the specified types.
		**/
		public TargetChatChosen() {}

		/**
		 * The chat needs to be chosen by the user among chats of the specified types.
		 *
		 * @param allowUserChats True, if private chats with ordinary users are allowed.
		 * @param allowBotChats True, if private chats with other bots are allowed.
		 * @param allowGroupChats True, if basic group and supergroup chats are allowed.
		 * @param allowChannelChats True, if channel chats are allowed.
		**/
		public TargetChatChosen(boolean allowUserChats,
				boolean allowBotChats,
				boolean allowGroupChats,
				boolean allowChannelChats) {
			this.allowUserChats = allowUserChats;
			this.allowBotChats = allowBotChats;
			this.allowGroupChats = allowGroupChats;
			this.allowChannelChats = allowChannelChats;
		}

		/**
		 * The chat needs to be chosen by the user among chats of the specified types.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TargetChatChosen(DataInput input) throws IOException {
			this.allowUserChats = input.readBoolean();
			this.allowBotChats = input.readBoolean();
			this.allowGroupChats = input.readBoolean();
			this.allowChannelChats = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TargetChatChosen.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TargetChatChosen.CONSTRUCTOR);
			output.writeBoolean(this.allowUserChats);
			output.writeBoolean(this.allowBotChats);
			output.writeBoolean(this.allowGroupChats);
			output.writeBoolean(this.allowChannelChats);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			TargetChatChosen targetChatChosen = (TargetChatChosen) o;
			if (this.allowUserChats != targetChatChosen.allowUserChats) {
				return false;
			}
			if (this.allowBotChats != targetChatChosen.allowBotChats) {
				return false;
			}
			if (this.allowGroupChats != targetChatChosen.allowGroupChats) {
				return false;
			}
			if (this.allowChannelChats != targetChatChosen.allowChannelChats) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.allowUserChats);
			return result;
		}
	}

	/**
	 * The chat needs to be open with the provided internal link.
	**/
	public static final class TargetChatInternalLink extends TargetChat {


		/**
		 * An internal link pointing to the chat.
		**/
		public InternalLinkType link;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -579301408;

		/**
		 * The chat needs to be open with the provided internal link.
		**/
		public TargetChatInternalLink() {}

		/**
		 * The chat needs to be open with the provided internal link.
		 *
		 * @param link An internal link pointing to the chat.
		**/
		public TargetChatInternalLink(InternalLinkType link) {
			this.link = link;
		}

		/**
		 * The chat needs to be open with the provided internal link.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TargetChatInternalLink(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InternalLinkTypeActiveSessions.CONSTRUCTOR: this.link = new InternalLinkTypeActiveSessions(input); break;
					case InternalLinkTypeAttachmentMenuBot.CONSTRUCTOR: this.link = new InternalLinkTypeAttachmentMenuBot(input); break;
					case InternalLinkTypeAuthenticationCode.CONSTRUCTOR: this.link = new InternalLinkTypeAuthenticationCode(input); break;
					case InternalLinkTypeBackground.CONSTRUCTOR: this.link = new InternalLinkTypeBackground(input); break;
					case InternalLinkTypeBotAddToChannel.CONSTRUCTOR: this.link = new InternalLinkTypeBotAddToChannel(input); break;
					case InternalLinkTypeBotStart.CONSTRUCTOR: this.link = new InternalLinkTypeBotStart(input); break;
					case InternalLinkTypeBotStartInGroup.CONSTRUCTOR: this.link = new InternalLinkTypeBotStartInGroup(input); break;
					case InternalLinkTypeChangePhoneNumber.CONSTRUCTOR: this.link = new InternalLinkTypeChangePhoneNumber(input); break;
					case InternalLinkTypeChatFolderInvite.CONSTRUCTOR: this.link = new InternalLinkTypeChatFolderInvite(input); break;
					case InternalLinkTypeChatFolderSettings.CONSTRUCTOR: this.link = new InternalLinkTypeChatFolderSettings(input); break;
					case InternalLinkTypeChatInvite.CONSTRUCTOR: this.link = new InternalLinkTypeChatInvite(input); break;
					case InternalLinkTypeDefaultMessageAutoDeleteTimerSettings.CONSTRUCTOR: this.link = new InternalLinkTypeDefaultMessageAutoDeleteTimerSettings(input); break;
					case InternalLinkTypeEditProfileSettings.CONSTRUCTOR: this.link = new InternalLinkTypeEditProfileSettings(input); break;
					case InternalLinkTypeGame.CONSTRUCTOR: this.link = new InternalLinkTypeGame(input); break;
					case InternalLinkTypeInstantView.CONSTRUCTOR: this.link = new InternalLinkTypeInstantView(input); break;
					case InternalLinkTypeInvoice.CONSTRUCTOR: this.link = new InternalLinkTypeInvoice(input); break;
					case InternalLinkTypeLanguagePack.CONSTRUCTOR: this.link = new InternalLinkTypeLanguagePack(input); break;
					case InternalLinkTypeLanguageSettings.CONSTRUCTOR: this.link = new InternalLinkTypeLanguageSettings(input); break;
					case InternalLinkTypeMessage.CONSTRUCTOR: this.link = new InternalLinkTypeMessage(input); break;
					case InternalLinkTypeMessageDraft.CONSTRUCTOR: this.link = new InternalLinkTypeMessageDraft(input); break;
					case InternalLinkTypePassportDataRequest.CONSTRUCTOR: this.link = new InternalLinkTypePassportDataRequest(input); break;
					case InternalLinkTypePhoneNumberConfirmation.CONSTRUCTOR: this.link = new InternalLinkTypePhoneNumberConfirmation(input); break;
					case InternalLinkTypePremiumFeatures.CONSTRUCTOR: this.link = new InternalLinkTypePremiumFeatures(input); break;
					case InternalLinkTypePrivacyAndSecuritySettings.CONSTRUCTOR: this.link = new InternalLinkTypePrivacyAndSecuritySettings(input); break;
					case InternalLinkTypeProxy.CONSTRUCTOR: this.link = new InternalLinkTypeProxy(input); break;
					case InternalLinkTypePublicChat.CONSTRUCTOR: this.link = new InternalLinkTypePublicChat(input); break;
					case InternalLinkTypeQrCodeAuthentication.CONSTRUCTOR: this.link = new InternalLinkTypeQrCodeAuthentication(input); break;
					case InternalLinkTypeRestorePurchases.CONSTRUCTOR: this.link = new InternalLinkTypeRestorePurchases(input); break;
					case InternalLinkTypeSettings.CONSTRUCTOR: this.link = new InternalLinkTypeSettings(input); break;
					case InternalLinkTypeStickerSet.CONSTRUCTOR: this.link = new InternalLinkTypeStickerSet(input); break;
					case InternalLinkTypeTheme.CONSTRUCTOR: this.link = new InternalLinkTypeTheme(input); break;
					case InternalLinkTypeThemeSettings.CONSTRUCTOR: this.link = new InternalLinkTypeThemeSettings(input); break;
					case InternalLinkTypeUnknownDeepLink.CONSTRUCTOR: this.link = new InternalLinkTypeUnknownDeepLink(input); break;
					case InternalLinkTypeUnsupportedProxy.CONSTRUCTOR: this.link = new InternalLinkTypeUnsupportedProxy(input); break;
					case InternalLinkTypeUserPhoneNumber.CONSTRUCTOR: this.link = new InternalLinkTypeUserPhoneNumber(input); break;
					case InternalLinkTypeUserToken.CONSTRUCTOR: this.link = new InternalLinkTypeUserToken(input); break;
					case InternalLinkTypeVideoChat.CONSTRUCTOR: this.link = new InternalLinkTypeVideoChat(input); break;
					case InternalLinkTypeWebApp.CONSTRUCTOR: this.link = new InternalLinkTypeWebApp(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TargetChatInternalLink.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TargetChatInternalLink.CONSTRUCTOR);
			if (this.link == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.link.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			TargetChatInternalLink targetChatInternalLink = (TargetChatInternalLink) o;
			if (!Objects.equals(this.link, targetChatInternalLink.link)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.link == null ? 0 : this.link.hashCode();
		}
	}

	/**
	 * Returns information about the availability of a temporary password,
	 * which can be used for payments.
	**/
	public static final class TemporaryPasswordState extends Object {


		/**
		 * True, if a temporary password is available.
		**/
		public boolean hasPassword;

		/**
		 * Time left before the temporary password expires, in seconds.
		**/
		public int validFor;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 939837410;

		/**
		 * Returns information about the availability of a temporary password, which can be used for payments.
		**/
		public TemporaryPasswordState() {}

		/**
		 * Returns information about the availability of a temporary password, which can be used for payments.
		 *
		 * @param hasPassword True, if a temporary password is available.
		 * @param validFor Time left before the temporary password expires, in seconds.
		**/
		public TemporaryPasswordState(boolean hasPassword, int validFor) {
			this.hasPassword = hasPassword;
			this.validFor = validFor;
		}

		/**
		 * Returns information about the availability of a temporary password, which can be used for payments.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TemporaryPasswordState(DataInput input) throws IOException {
			this.hasPassword = input.readBoolean();
			this.validFor = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TemporaryPasswordState.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TemporaryPasswordState.CONSTRUCTOR);
			output.writeBoolean(this.hasPassword);
			output.writeInt(this.validFor);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			TemporaryPasswordState temporaryPasswordState = (TemporaryPasswordState) o;
			if (this.hasPassword != temporaryPasswordState.hasPassword) {
				return false;
			}
			if (this.validFor != temporaryPasswordState.validFor) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.hasPassword);
			return result;
		}
	}

	/**
	 * Contains Telegram terms of service.
	**/
	public static final class TermsOfService extends Object {


		/**
		 * Text of the terms of service.
		**/
		public FormattedText text;

		/**
		 * The minimum age of a user to be able to accept the terms; 0 if age isn&#039;t restricted.
		**/
		public int minUserAge;

		/**
		 * True, if a blocking popup with terms of service must be shown to the user.
		**/
		public boolean showPopup;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 739422597;

		/**
		 * Contains Telegram terms of service.
		**/
		public TermsOfService() {}

		/**
		 * Contains Telegram terms of service.
		 *
		 * @param text Text of the terms of service.
		 * @param minUserAge The minimum age of a user to be able to accept the terms; 0 if age isn&#039;t restricted.
		 * @param showPopup True, if a blocking popup with terms of service must be shown to the user.
		**/
		public TermsOfService(FormattedText text, int minUserAge, boolean showPopup) {
			this.text = text;
			this.minUserAge = minUserAge;
			this.showPopup = showPopup;
		}

		/**
		 * Contains Telegram terms of service.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TermsOfService(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (FormattedText.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.text = new FormattedText(input);
			}
			this.minUserAge = input.readInt();
			this.showPopup = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TermsOfService.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TermsOfService.CONSTRUCTOR);
			if (this.text == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.text.serialize(output);
			}
			output.writeInt(this.minUserAge);
			output.writeBoolean(this.showPopup);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			TermsOfService termsOfService = (TermsOfService) o;
			if (!Objects.equals(this.text, termsOfService.text)) {
				return false;
			}
			if (this.minUserAge != termsOfService.minUserAge) {
				return false;
			}
			if (this.showPopup != termsOfService.showPopup) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.minUserAge);
			result = result * 31 + (this.text == null ? 0 : this.text.hashCode());
			return result;
		}
	}

	/**
	 * A simple object containing a sequence of bytes; for testing only.
	**/
	public static final class TestBytes extends Object {


		/**
		 * Bytes.
		**/
		public byte[] value;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1541225250;

		/**
		 * A simple object containing a sequence of bytes; for testing only.
		**/
		public TestBytes() {}

		/**
		 * A simple object containing a sequence of bytes; for testing only.
		 *
		 * @param value Bytes.
		**/
		public TestBytes(byte[] value) {
			this.value = value;
		}

		/**
		 * A simple object containing a sequence of bytes; for testing only.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TestBytes(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.value = new byte[input.readInt()];
				input.readFully(this.value);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TestBytes.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TestBytes.CONSTRUCTOR);
			if (this.value == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.value.length);
				output.write(this.value);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			TestBytes testBytes = (TestBytes) o;
			if (this.value != testBytes.value) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.value);
		}
	}

	/**
	 * A simple object containing a number; for testing only.
	**/
	public static final class TestInt extends Object {


		/**
		 * Number.
		**/
		public int value;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -574804983;

		/**
		 * A simple object containing a number; for testing only.
		**/
		public TestInt() {}

		/**
		 * A simple object containing a number; for testing only.
		 *
		 * @param value Number.
		**/
		public TestInt(int value) {
			this.value = value;
		}

		/**
		 * A simple object containing a number; for testing only.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TestInt(DataInput input) throws IOException {
			this.value = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TestInt.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TestInt.CONSTRUCTOR);
			output.writeInt(this.value);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			TestInt testInt = (TestInt) o;
			if (this.value != testInt.value) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.value);
		}
	}

	/**
	 * A simple object containing a string; for testing only.
	**/
	public static final class TestString extends Object {


		/**
		 * String.
		**/
		public String value;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -27891572;

		/**
		 * A simple object containing a string; for testing only.
		**/
		public TestString() {}

		/**
		 * A simple object containing a string; for testing only.
		 *
		 * @param value String.
		**/
		public TestString(String value) {
			this.value = value;
		}

		/**
		 * A simple object containing a string; for testing only.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TestString(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] valueTmp = new byte[input.readInt()];
				input.readFully(valueTmp);
				this.value = new String(valueTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TestString.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TestString.CONSTRUCTOR);
			if (this.value == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] valueTmp = this.value.getBytes(StandardCharsets.UTF_8);
				output.writeInt(valueTmp.length);
				output.write(valueTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			TestString testString = (TestString) o;
			if (this.value != testString.value) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.value == null ? 0 : this.value.hashCode();
		}
	}

	/**
	 * A simple object containing a vector of numbers; for testing only.
	**/
	public static final class TestVectorInt extends Object {


		/**
		 * Vector of numbers.
		**/
		public int[] value;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 593682027;

		/**
		 * A simple object containing a vector of numbers; for testing only.
		**/
		public TestVectorInt() {}

		/**
		 * A simple object containing a vector of numbers; for testing only.
		 *
		 * @param value Vector of numbers.
		**/
		public TestVectorInt(int[] value) {
			this.value = value;
		}

		/**
		 * A simple object containing a vector of numbers; for testing only.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TestVectorInt(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.value = new int[input.readInt()];
				for (int i = 0; i < this.value.length; i++) {
					this.value[i] = input.readInt();
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TestVectorInt.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TestVectorInt.CONSTRUCTOR);
			if (this.value == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.value.length);
				for (int i = 0; i < this.value.length; i++) {
					output.writeInt(this.value[i]);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			TestVectorInt testVectorInt = (TestVectorInt) o;
			if (!Arrays.equals(this.value, testVectorInt.value)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.value);
		}
	}

	/**
	 * A simple object containing a vector of objects that hold a number;
	 * for testing only.
	**/
	public static final class TestVectorIntObject extends Object {


		/**
		 * Vector of objects.
		**/
		public TestInt[] value;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 125891546;

		/**
		 * A simple object containing a vector of objects that hold a number; for testing only.
		**/
		public TestVectorIntObject() {}

		/**
		 * A simple object containing a vector of objects that hold a number; for testing only.
		 *
		 * @param value Vector of objects.
		**/
		public TestVectorIntObject(TestInt[] value) {
			this.value = value;
		}

		/**
		 * A simple object containing a vector of objects that hold a number; for testing only.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TestVectorIntObject(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.value = new TestInt[input.readInt()];
				for (int i = 0; i < this.value.length; i++) {
					if (TestInt.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.value[i] = new TestInt(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TestVectorIntObject.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TestVectorIntObject.CONSTRUCTOR);
			if (this.value == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.value.length);
				for (int i = 0; i < this.value.length; i++) {
					this.value[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			TestVectorIntObject testVectorIntObject = (TestVectorIntObject) o;
			if (!Arrays.equals(this.value, testVectorIntObject.value)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.value);
		}
	}

	/**
	 * A simple object containing a vector of strings; for testing only.
	**/
	public static final class TestVectorString extends Object {


		/**
		 * Vector of strings.
		**/
		public String[] value;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 79339995;

		/**
		 * A simple object containing a vector of strings; for testing only.
		**/
		public TestVectorString() {}

		/**
		 * A simple object containing a vector of strings; for testing only.
		 *
		 * @param value Vector of strings.
		**/
		public TestVectorString(String[] value) {
			this.value = value;
		}

		/**
		 * A simple object containing a vector of strings; for testing only.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TestVectorString(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.value = new String[input.readInt()];
				for (int i = 0; i < this.value.length; i++) {
					byte[] valueTmp = new byte[input.readInt()];
					input.readFully(valueTmp);
					this.value[i] = new String(valueTmp, StandardCharsets.UTF_8);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TestVectorString.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TestVectorString.CONSTRUCTOR);
			if (this.value == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.value.length);
				for (int i = 0; i < this.value.length; i++) {
					byte[] valueTmp = this.value[i].getBytes(StandardCharsets.UTF_8);
					output.writeInt(valueTmp.length);
					output.write(valueTmp);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			TestVectorString testVectorString = (TestVectorString) o;
			if (!Arrays.equals(this.value, testVectorString.value)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.value);
		}
	}

	/**
	 * A simple object containing a vector of objects that hold a string;
	 * for testing only.
	**/
	public static final class TestVectorStringObject extends Object {


		/**
		 * Vector of objects.
		**/
		public TestString[] value;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 80780537;

		/**
		 * A simple object containing a vector of objects that hold a string; for testing only.
		**/
		public TestVectorStringObject() {}

		/**
		 * A simple object containing a vector of objects that hold a string; for testing only.
		 *
		 * @param value Vector of objects.
		**/
		public TestVectorStringObject(TestString[] value) {
			this.value = value;
		}

		/**
		 * A simple object containing a vector of objects that hold a string; for testing only.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TestVectorStringObject(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.value = new TestString[input.readInt()];
				for (int i = 0; i < this.value.length; i++) {
					if (TestString.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.value[i] = new TestString(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TestVectorStringObject.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TestVectorStringObject.CONSTRUCTOR);
			if (this.value == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.value.length);
				for (int i = 0; i < this.value.length; i++) {
					this.value[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			TestVectorStringObject testVectorStringObject = (TestVectorStringObject) o;
			if (!Arrays.equals(this.value, testVectorStringObject.value)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.value);
		}
	}

	/**
	 * Contains some text.
	**/
	public static final class Text extends Object {


		/**
		 * Text.
		**/
		public String text;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 578181272;

		/**
		 * Contains some text.
		**/
		public Text() {}

		/**
		 * Contains some text.
		 *
		 * @param text Text.
		**/
		public Text(String text) {
			this.text = text;
		}

		/**
		 * Contains some text.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public Text(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] textTmp = new byte[input.readInt()];
				input.readFully(textTmp);
				this.text = new String(textTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return Text.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(Text.CONSTRUCTOR);
			if (this.text == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] textTmp = this.text.getBytes(StandardCharsets.UTF_8);
				output.writeInt(textTmp.length);
				output.write(textTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			Text text = (Text) o;
			if (this.text != text.text) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.text == null ? 0 : this.text.hashCode();
		}
	}

	/**
	 * Contains a list of text entities.
	**/
	public static final class TextEntities extends Object {


		/**
		 * List of text entities.
		**/
		public TextEntity[] entities;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -933199172;

		/**
		 * Contains a list of text entities.
		**/
		public TextEntities() {}

		/**
		 * Contains a list of text entities.
		 *
		 * @param entities List of text entities.
		**/
		public TextEntities(TextEntity[] entities) {
			this.entities = entities;
		}

		/**
		 * Contains a list of text entities.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TextEntities(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.entities = new TextEntity[input.readInt()];
				for (int i = 0; i < this.entities.length; i++) {
					if (TextEntity.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.entities[i] = new TextEntity(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TextEntities.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TextEntities.CONSTRUCTOR);
			if (this.entities == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.entities.length);
				for (int i = 0; i < this.entities.length; i++) {
					this.entities[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			TextEntities textEntities = (TextEntities) o;
			if (!Arrays.equals(this.entities, textEntities.entities)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.entities);
		}
	}

	/**
	 * Represents a part of the text that needs to be formatted in some
	 * unusual way.
	**/
	public static final class TextEntity extends Object {


		/**
		 * Offset of the entity, in UTF-16 code units.
		**/
		public int offset;

		/**
		 * Length of the entity, in UTF-16 code units.
		**/
		public int length;

		/**
		 * Type of the entity.
		**/
		public TextEntityType type;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1951688280;

		/**
		 * Represents a part of the text that needs to be formatted in some unusual way.
		**/
		public TextEntity() {}

		/**
		 * Represents a part of the text that needs to be formatted in some unusual way.
		 *
		 * @param offset Offset of the entity, in UTF-16 code units.
		 * @param length Length of the entity, in UTF-16 code units.
		 * @param type Type of the entity.
		**/
		public TextEntity(int offset, int length, TextEntityType type) {
			this.offset = offset;
			this.length = length;
			this.type = type;
		}

		/**
		 * Represents a part of the text that needs to be formatted in some unusual way.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TextEntity(DataInput input) throws IOException {
			this.offset = input.readInt();
			this.length = input.readInt();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case TextEntityTypeMention.CONSTRUCTOR: this.type = new TextEntityTypeMention(input); break;
					case TextEntityTypeHashtag.CONSTRUCTOR: this.type = new TextEntityTypeHashtag(input); break;
					case TextEntityTypeCashtag.CONSTRUCTOR: this.type = new TextEntityTypeCashtag(input); break;
					case TextEntityTypeBotCommand.CONSTRUCTOR: this.type = new TextEntityTypeBotCommand(input); break;
					case TextEntityTypeUrl.CONSTRUCTOR: this.type = new TextEntityTypeUrl(input); break;
					case TextEntityTypeEmailAddress.CONSTRUCTOR: this.type = new TextEntityTypeEmailAddress(input); break;
					case TextEntityTypePhoneNumber.CONSTRUCTOR: this.type = new TextEntityTypePhoneNumber(input); break;
					case TextEntityTypeBankCardNumber.CONSTRUCTOR: this.type = new TextEntityTypeBankCardNumber(input); break;
					case TextEntityTypeBold.CONSTRUCTOR: this.type = new TextEntityTypeBold(input); break;
					case TextEntityTypeItalic.CONSTRUCTOR: this.type = new TextEntityTypeItalic(input); break;
					case TextEntityTypeUnderline.CONSTRUCTOR: this.type = new TextEntityTypeUnderline(input); break;
					case TextEntityTypeStrikethrough.CONSTRUCTOR: this.type = new TextEntityTypeStrikethrough(input); break;
					case TextEntityTypeSpoiler.CONSTRUCTOR: this.type = new TextEntityTypeSpoiler(input); break;
					case TextEntityTypeCode.CONSTRUCTOR: this.type = new TextEntityTypeCode(input); break;
					case TextEntityTypePre.CONSTRUCTOR: this.type = new TextEntityTypePre(input); break;
					case TextEntityTypePreCode.CONSTRUCTOR: this.type = new TextEntityTypePreCode(input); break;
					case TextEntityTypeTextUrl.CONSTRUCTOR: this.type = new TextEntityTypeTextUrl(input); break;
					case TextEntityTypeMentionName.CONSTRUCTOR: this.type = new TextEntityTypeMentionName(input); break;
					case TextEntityTypeCustomEmoji.CONSTRUCTOR: this.type = new TextEntityTypeCustomEmoji(input); break;
					case TextEntityTypeMediaTimestamp.CONSTRUCTOR: this.type = new TextEntityTypeMediaTimestamp(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TextEntity.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TextEntity.CONSTRUCTOR);
			output.writeInt(this.offset);
			output.writeInt(this.length);
			if (this.type == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.type.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			TextEntity textEntity = (TextEntity) o;
			if (this.offset != textEntity.offset) {
				return false;
			}
			if (this.length != textEntity.length) {
				return false;
			}
			if (!Objects.equals(this.type, textEntity.type)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.offset);
			result = result * 31 + (this.type == null ? 0 : this.type.hashCode());
			return result;
		}
	}

	/**
	 * A mention of a user, a supergroup, or a channel by their username.
	**/
	public static final class TextEntityTypeMention extends TextEntityType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 934535013;

		/**
		 * A mention of a user, a supergroup, or a channel by their username.
		**/
		public TextEntityTypeMention() {}

		/**
		 * A mention of a user, a supergroup, or a channel by their username.
		 *
		**/

		/**
		 * A mention of a user, a supergroup, or a channel by their username.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TextEntityTypeMention(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TextEntityTypeMention.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TextEntityTypeMention.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return TextEntityTypeMention.CONSTRUCTOR;
		}
	}

	/**
	 * A hashtag text, beginning with &quot;#&quot;.
	**/
	public static final class TextEntityTypeHashtag extends TextEntityType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1023958307;

		/**
		 * A hashtag text, beginning with &quot;#&quot;.
		**/
		public TextEntityTypeHashtag() {}

		/**
		 * A hashtag text, beginning with &quot;#&quot;.
		 *
		**/

		/**
		 * A hashtag text, beginning with &quot;#&quot;.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TextEntityTypeHashtag(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TextEntityTypeHashtag.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TextEntityTypeHashtag.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return TextEntityTypeHashtag.CONSTRUCTOR;
		}
	}

	/**
	 * A cashtag text, beginning with &quot;$&quot; and consisting of
	 * capital English letters (e.g., &quot;$USD&quot;).
	**/
	public static final class TextEntityTypeCashtag extends TextEntityType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1222915915;

		/**
		 * A cashtag text, beginning with &quot;$&quot; and consisting of capital English letters (e.g., &quot;$USD&quot;).
		**/
		public TextEntityTypeCashtag() {}

		/**
		 * A cashtag text, beginning with &quot;$&quot; and consisting of capital English letters (e.g., &quot;$USD&quot;).
		 *
		**/

		/**
		 * A cashtag text, beginning with &quot;$&quot; and consisting of capital English letters (e.g., &quot;$USD&quot;).
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TextEntityTypeCashtag(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TextEntityTypeCashtag.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TextEntityTypeCashtag.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return TextEntityTypeCashtag.CONSTRUCTOR;
		}
	}

	/**
	 * A bot command, beginning with &quot;/&quot;.
	**/
	public static final class TextEntityTypeBotCommand extends TextEntityType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1150997581;

		/**
		 * A bot command, beginning with &quot;/&quot;.
		**/
		public TextEntityTypeBotCommand() {}

		/**
		 * A bot command, beginning with &quot;/&quot;.
		 *
		**/

		/**
		 * A bot command, beginning with &quot;/&quot;.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TextEntityTypeBotCommand(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TextEntityTypeBotCommand.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TextEntityTypeBotCommand.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return TextEntityTypeBotCommand.CONSTRUCTOR;
		}
	}

	/**
	 * An HTTP URL.
	**/
	public static final class TextEntityTypeUrl extends TextEntityType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1312762756;

		/**
		 * An HTTP URL.
		**/
		public TextEntityTypeUrl() {}

		/**
		 * An HTTP URL.
		 *
		**/

		/**
		 * An HTTP URL.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TextEntityTypeUrl(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TextEntityTypeUrl.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TextEntityTypeUrl.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return TextEntityTypeUrl.CONSTRUCTOR;
		}
	}

	/**
	 * An email address.
	**/
	public static final class TextEntityTypeEmailAddress extends TextEntityType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1425545249;

		/**
		 * An email address.
		**/
		public TextEntityTypeEmailAddress() {}

		/**
		 * An email address.
		 *
		**/

		/**
		 * An email address.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TextEntityTypeEmailAddress(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TextEntityTypeEmailAddress.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TextEntityTypeEmailAddress.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return TextEntityTypeEmailAddress.CONSTRUCTOR;
		}
	}

	/**
	 * A phone number.
	**/
	public static final class TextEntityTypePhoneNumber extends TextEntityType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1160140246;

		/**
		 * A phone number.
		**/
		public TextEntityTypePhoneNumber() {}

		/**
		 * A phone number.
		 *
		**/

		/**
		 * A phone number.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TextEntityTypePhoneNumber(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TextEntityTypePhoneNumber.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TextEntityTypePhoneNumber.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return TextEntityTypePhoneNumber.CONSTRUCTOR;
		}
	}

	/**
	 * A bank card number. The getBankCardInfo method can be used to get
	 * information about the bank card.
	**/
	public static final class TextEntityTypeBankCardNumber extends TextEntityType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 105986320;

		/**
		 * A bank card number. The getBankCardInfo method can be used to get information about the bank card.
		**/
		public TextEntityTypeBankCardNumber() {}

		/**
		 * A bank card number. The getBankCardInfo method can be used to get information about the bank card.
		 *
		**/

		/**
		 * A bank card number. The getBankCardInfo method can be used to get information about the bank card.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TextEntityTypeBankCardNumber(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TextEntityTypeBankCardNumber.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TextEntityTypeBankCardNumber.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return TextEntityTypeBankCardNumber.CONSTRUCTOR;
		}
	}

	/**
	 * A bold text.
	**/
	public static final class TextEntityTypeBold extends TextEntityType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1128210000;

		/**
		 * A bold text.
		**/
		public TextEntityTypeBold() {}

		/**
		 * A bold text.
		 *
		**/

		/**
		 * A bold text.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TextEntityTypeBold(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TextEntityTypeBold.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TextEntityTypeBold.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return TextEntityTypeBold.CONSTRUCTOR;
		}
	}

	/**
	 * An italic text.
	**/
	public static final class TextEntityTypeItalic extends TextEntityType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -118253987;

		/**
		 * An italic text.
		**/
		public TextEntityTypeItalic() {}

		/**
		 * An italic text.
		 *
		**/

		/**
		 * An italic text.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TextEntityTypeItalic(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TextEntityTypeItalic.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TextEntityTypeItalic.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return TextEntityTypeItalic.CONSTRUCTOR;
		}
	}

	/**
	 * An underlined text.
	**/
	public static final class TextEntityTypeUnderline extends TextEntityType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 792317842;

		/**
		 * An underlined text.
		**/
		public TextEntityTypeUnderline() {}

		/**
		 * An underlined text.
		 *
		**/

		/**
		 * An underlined text.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TextEntityTypeUnderline(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TextEntityTypeUnderline.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TextEntityTypeUnderline.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return TextEntityTypeUnderline.CONSTRUCTOR;
		}
	}

	/**
	 * A strikethrough text.
	**/
	public static final class TextEntityTypeStrikethrough extends TextEntityType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 961529082;

		/**
		 * A strikethrough text.
		**/
		public TextEntityTypeStrikethrough() {}

		/**
		 * A strikethrough text.
		 *
		**/

		/**
		 * A strikethrough text.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TextEntityTypeStrikethrough(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TextEntityTypeStrikethrough.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TextEntityTypeStrikethrough.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return TextEntityTypeStrikethrough.CONSTRUCTOR;
		}
	}

	/**
	 * A spoiler text.
	**/
	public static final class TextEntityTypeSpoiler extends TextEntityType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 544019899;

		/**
		 * A spoiler text.
		**/
		public TextEntityTypeSpoiler() {}

		/**
		 * A spoiler text.
		 *
		**/

		/**
		 * A spoiler text.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TextEntityTypeSpoiler(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TextEntityTypeSpoiler.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TextEntityTypeSpoiler.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return TextEntityTypeSpoiler.CONSTRUCTOR;
		}
	}

	/**
	 * Text that must be formatted as if inside a code HTML tag.
	**/
	public static final class TextEntityTypeCode extends TextEntityType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -974534326;

		/**
		 * Text that must be formatted as if inside a code HTML tag.
		**/
		public TextEntityTypeCode() {}

		/**
		 * Text that must be formatted as if inside a code HTML tag.
		 *
		**/

		/**
		 * Text that must be formatted as if inside a code HTML tag.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TextEntityTypeCode(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TextEntityTypeCode.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TextEntityTypeCode.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return TextEntityTypeCode.CONSTRUCTOR;
		}
	}

	/**
	 * Text that must be formatted as if inside a pre HTML tag.
	**/
	public static final class TextEntityTypePre extends TextEntityType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1648958606;

		/**
		 * Text that must be formatted as if inside a pre HTML tag.
		**/
		public TextEntityTypePre() {}

		/**
		 * Text that must be formatted as if inside a pre HTML tag.
		 *
		**/

		/**
		 * Text that must be formatted as if inside a pre HTML tag.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TextEntityTypePre(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TextEntityTypePre.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TextEntityTypePre.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return TextEntityTypePre.CONSTRUCTOR;
		}
	}

	/**
	 * Text that must be formatted as if inside pre, and code HTML tags.
	**/
	public static final class TextEntityTypePreCode extends TextEntityType {


		/**
		 * Programming language of the code; as defined by the sender.
		**/
		public String language;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -945325397;

		/**
		 * Text that must be formatted as if inside pre, and code HTML tags.
		**/
		public TextEntityTypePreCode() {}

		/**
		 * Text that must be formatted as if inside pre, and code HTML tags.
		 *
		 * @param language Programming language of the code; as defined by the sender.
		**/
		public TextEntityTypePreCode(String language) {
			this.language = language;
		}

		/**
		 * Text that must be formatted as if inside pre, and code HTML tags.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TextEntityTypePreCode(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] languageTmp = new byte[input.readInt()];
				input.readFully(languageTmp);
				this.language = new String(languageTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TextEntityTypePreCode.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TextEntityTypePreCode.CONSTRUCTOR);
			if (this.language == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] languageTmp = this.language.getBytes(StandardCharsets.UTF_8);
				output.writeInt(languageTmp.length);
				output.write(languageTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			TextEntityTypePreCode textEntityTypePreCode = (TextEntityTypePreCode) o;
			if (this.language != textEntityTypePreCode.language) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.language == null ? 0 : this.language.hashCode();
		}
	}

	/**
	 * A text description shown instead of a raw URL.
	**/
	public static final class TextEntityTypeTextUrl extends TextEntityType {


		/**
		 * HTTP or tg:// URL to be opened when the link is clicked.
		**/
		public String url;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 445719651;

		/**
		 * A text description shown instead of a raw URL.
		**/
		public TextEntityTypeTextUrl() {}

		/**
		 * A text description shown instead of a raw URL.
		 *
		 * @param url HTTP or tg:// URL to be opened when the link is clicked.
		**/
		public TextEntityTypeTextUrl(String url) {
			this.url = url;
		}

		/**
		 * A text description shown instead of a raw URL.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TextEntityTypeTextUrl(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] urlTmp = new byte[input.readInt()];
				input.readFully(urlTmp);
				this.url = new String(urlTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TextEntityTypeTextUrl.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TextEntityTypeTextUrl.CONSTRUCTOR);
			if (this.url == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] urlTmp = this.url.getBytes(StandardCharsets.UTF_8);
				output.writeInt(urlTmp.length);
				output.write(urlTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			TextEntityTypeTextUrl textEntityTypeTextUrl = (TextEntityTypeTextUrl) o;
			if (this.url != textEntityTypeTextUrl.url) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.url == null ? 0 : this.url.hashCode();
		}
	}

	/**
	 * A text shows instead of a raw mention of the user (e.g., when the
	 * user has no username).
	**/
	public static final class TextEntityTypeMentionName extends TextEntityType {


		/**
		 * Identifier of the mentioned user.
		**/
		public long userId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1570974289;

		/**
		 * A text shows instead of a raw mention of the user (e.g., when the user has no username).
		**/
		public TextEntityTypeMentionName() {}

		/**
		 * A text shows instead of a raw mention of the user (e.g., when the user has no username).
		 *
		 * @param userId Identifier of the mentioned user.
		**/
		public TextEntityTypeMentionName(long userId) {
			this.userId = userId;
		}

		/**
		 * A text shows instead of a raw mention of the user (e.g., when the user has no username).
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TextEntityTypeMentionName(DataInput input) throws IOException {
			this.userId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TextEntityTypeMentionName.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TextEntityTypeMentionName.CONSTRUCTOR);
			output.writeLong(this.userId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			TextEntityTypeMentionName textEntityTypeMentionName = (TextEntityTypeMentionName) o;
			if (this.userId != textEntityTypeMentionName.userId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.userId);
		}
	}

	/**
	 * A custom emoji. The text behind a custom emoji must be an emoji. Only
	 * premium users can use premium custom emoji.
	**/
	public static final class TextEntityTypeCustomEmoji extends TextEntityType {


		/**
		 * Unique identifier of the custom emoji.
		**/
		public long customEmojiId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1724820677;

		/**
		 * A custom emoji. The text behind a custom emoji must be an emoji. Only premium users can use premium custom emoji.
		**/
		public TextEntityTypeCustomEmoji() {}

		/**
		 * A custom emoji. The text behind a custom emoji must be an emoji. Only premium users can use premium custom emoji.
		 *
		 * @param customEmojiId Unique identifier of the custom emoji.
		**/
		public TextEntityTypeCustomEmoji(long customEmojiId) {
			this.customEmojiId = customEmojiId;
		}

		/**
		 * A custom emoji. The text behind a custom emoji must be an emoji. Only premium users can use premium custom emoji.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TextEntityTypeCustomEmoji(DataInput input) throws IOException {
			this.customEmojiId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TextEntityTypeCustomEmoji.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TextEntityTypeCustomEmoji.CONSTRUCTOR);
			output.writeLong(this.customEmojiId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			TextEntityTypeCustomEmoji textEntityTypeCustomEmoji = (TextEntityTypeCustomEmoji) o;
			if (this.customEmojiId != textEntityTypeCustomEmoji.customEmojiId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.customEmojiId);
		}
	}

	/**
	 * A media timestamp.
	**/
	public static final class TextEntityTypeMediaTimestamp extends TextEntityType {


		/**
		 * Timestamp from which a video/audio/video note/voice note playing must start, in seconds. The media can be in the content or the web page preview of the current message, or in the same places in the replied message.
		**/
		public int mediaTimestamp;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1841898992;

		/**
		 * A media timestamp.
		**/
		public TextEntityTypeMediaTimestamp() {}

		/**
		 * A media timestamp.
		 *
		 * @param mediaTimestamp Timestamp from which a video/audio/video note/voice note playing must start, in seconds. The media can be in the content or the web page preview of the current message, or in the same places in the replied message.
		**/
		public TextEntityTypeMediaTimestamp(int mediaTimestamp) {
			this.mediaTimestamp = mediaTimestamp;
		}

		/**
		 * A media timestamp.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TextEntityTypeMediaTimestamp(DataInput input) throws IOException {
			this.mediaTimestamp = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TextEntityTypeMediaTimestamp.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TextEntityTypeMediaTimestamp.CONSTRUCTOR);
			output.writeInt(this.mediaTimestamp);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			TextEntityTypeMediaTimestamp textEntityTypeMediaTimestamp = (TextEntityTypeMediaTimestamp) o;
			if (this.mediaTimestamp != textEntityTypeMediaTimestamp.mediaTimestamp) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.mediaTimestamp);
		}
	}

	/**
	 * The text uses Markdown-style formatting.
	**/
	public static final class TextParseModeMarkdown extends TextParseMode {


		/**
		 * Version of the parser: 0 or 1 - Telegram Bot API &quot;Markdown&quot; parse mode, 2 - Telegram Bot API &quot;MarkdownV2&quot; parse mode.
		**/
		public int version;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 360073407;

		/**
		 * The text uses Markdown-style formatting.
		**/
		public TextParseModeMarkdown() {}

		/**
		 * The text uses Markdown-style formatting.
		 *
		 * @param version Version of the parser: 0 or 1 - Telegram Bot API &quot;Markdown&quot; parse mode, 2 - Telegram Bot API &quot;MarkdownV2&quot; parse mode.
		**/
		public TextParseModeMarkdown(int version) {
			this.version = version;
		}

		/**
		 * The text uses Markdown-style formatting.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TextParseModeMarkdown(DataInput input) throws IOException {
			this.version = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TextParseModeMarkdown.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TextParseModeMarkdown.CONSTRUCTOR);
			output.writeInt(this.version);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			TextParseModeMarkdown textParseModeMarkdown = (TextParseModeMarkdown) o;
			if (this.version != textParseModeMarkdown.version) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.version);
		}
	}

	/**
	 * The text uses HTML-style formatting. The same as Telegram Bot API
	 * &quot;HTML&quot; parse mode.
	**/
	public static final class TextParseModeHTML extends TextParseMode {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1660208627;

		/**
		 * The text uses HTML-style formatting. The same as Telegram Bot API &quot;HTML&quot; parse mode.
		**/
		public TextParseModeHTML() {}

		/**
		 * The text uses HTML-style formatting. The same as Telegram Bot API &quot;HTML&quot; parse mode.
		 *
		**/

		/**
		 * The text uses HTML-style formatting. The same as Telegram Bot API &quot;HTML&quot; parse mode.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TextParseModeHTML(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TextParseModeHTML.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TextParseModeHTML.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return TextParseModeHTML.CONSTRUCTOR;
		}
	}

	/**
	 * Contains parameters of the application theme.
	**/
	public static final class ThemeParameters extends Object {


		/**
		 * A color of the background in the RGB24 format.
		**/
		public int backgroundColor;

		/**
		 * A secondary color for the background in the RGB24 format.
		**/
		public int secondaryBackgroundColor;

		/**
		 * A color of text in the RGB24 format.
		**/
		public int textColor;

		/**
		 * A color of hints in the RGB24 format.
		**/
		public int hintColor;

		/**
		 * A color of links in the RGB24 format.
		**/
		public int linkColor;

		/**
		 * A color of the buttons in the RGB24 format.
		**/
		public int buttonColor;

		/**
		 * A color of text on the buttons in the RGB24 format.
		**/
		public int buttonTextColor;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -644809106;

		/**
		 * Contains parameters of the application theme.
		**/
		public ThemeParameters() {}

		/**
		 * Contains parameters of the application theme.
		 *
		 * @param backgroundColor A color of the background in the RGB24 format.
		 * @param secondaryBackgroundColor A secondary color for the background in the RGB24 format.
		 * @param textColor A color of text in the RGB24 format.
		 * @param hintColor A color of hints in the RGB24 format.
		 * @param linkColor A color of links in the RGB24 format.
		 * @param buttonColor A color of the buttons in the RGB24 format.
		 * @param buttonTextColor A color of text on the buttons in the RGB24 format.
		**/
		public ThemeParameters(int backgroundColor,
				int secondaryBackgroundColor,
				int textColor,
				int hintColor,
				int linkColor,
				int buttonColor,
				int buttonTextColor) {
			this.backgroundColor = backgroundColor;
			this.secondaryBackgroundColor = secondaryBackgroundColor;
			this.textColor = textColor;
			this.hintColor = hintColor;
			this.linkColor = linkColor;
			this.buttonColor = buttonColor;
			this.buttonTextColor = buttonTextColor;
		}

		/**
		 * Contains parameters of the application theme.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ThemeParameters(DataInput input) throws IOException {
			this.backgroundColor = input.readInt();
			this.secondaryBackgroundColor = input.readInt();
			this.textColor = input.readInt();
			this.hintColor = input.readInt();
			this.linkColor = input.readInt();
			this.buttonColor = input.readInt();
			this.buttonTextColor = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ThemeParameters.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ThemeParameters.CONSTRUCTOR);
			output.writeInt(this.backgroundColor);
			output.writeInt(this.secondaryBackgroundColor);
			output.writeInt(this.textColor);
			output.writeInt(this.hintColor);
			output.writeInt(this.linkColor);
			output.writeInt(this.buttonColor);
			output.writeInt(this.buttonTextColor);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ThemeParameters themeParameters = (ThemeParameters) o;
			if (this.backgroundColor != themeParameters.backgroundColor) {
				return false;
			}
			if (this.secondaryBackgroundColor != themeParameters.secondaryBackgroundColor) {
				return false;
			}
			if (this.textColor != themeParameters.textColor) {
				return false;
			}
			if (this.hintColor != themeParameters.hintColor) {
				return false;
			}
			if (this.linkColor != themeParameters.linkColor) {
				return false;
			}
			if (this.buttonColor != themeParameters.buttonColor) {
				return false;
			}
			if (this.buttonTextColor != themeParameters.buttonTextColor) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.backgroundColor);
			return result;
		}
	}

	/**
	 * Describes theme settings.
	**/
	public static final class ThemeSettings extends Object {


		/**
		 * Theme accent color in ARGB format.
		**/
		public int accentColor;

		/**
		 * The background to be used in chats; may be null.
		**/
		public Background background;

		/**
		 * The fill to be used as a background for outgoing messages.
		**/
		public BackgroundFill outgoingMessageFill;

		/**
		 * If true, the freeform gradient fill needs to be animated on every sent message.
		**/
		public boolean animateOutgoingMessageFill;

		/**
		 * Accent color of outgoing messages in ARGB format.
		**/
		public int outgoingMessageAccentColor;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -62120942;

		/**
		 * Describes theme settings.
		**/
		public ThemeSettings() {}

		/**
		 * Describes theme settings.
		 *
		 * @param accentColor Theme accent color in ARGB format.
		 * @param background The background to be used in chats; may be null.
		 * @param outgoingMessageFill The fill to be used as a background for outgoing messages.
		 * @param animateOutgoingMessageFill If true, the freeform gradient fill needs to be animated on every sent message.
		 * @param outgoingMessageAccentColor Accent color of outgoing messages in ARGB format.
		**/
		public ThemeSettings(int accentColor,
				Background background,
				BackgroundFill outgoingMessageFill,
				boolean animateOutgoingMessageFill,
				int outgoingMessageAccentColor) {
			this.accentColor = accentColor;
			this.background = background;
			this.outgoingMessageFill = outgoingMessageFill;
			this.animateOutgoingMessageFill = animateOutgoingMessageFill;
			this.outgoingMessageAccentColor = outgoingMessageAccentColor;
		}

		/**
		 * Describes theme settings.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ThemeSettings(DataInput input) throws IOException {
			this.accentColor = input.readInt();
			if (input.readBoolean()) {
				if (Background.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.background = new Background(input);
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case BackgroundFillSolid.CONSTRUCTOR: this.outgoingMessageFill = new BackgroundFillSolid(input); break;
					case BackgroundFillGradient.CONSTRUCTOR: this.outgoingMessageFill = new BackgroundFillGradient(input); break;
					case BackgroundFillFreeformGradient.CONSTRUCTOR: this.outgoingMessageFill = new BackgroundFillFreeformGradient(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.animateOutgoingMessageFill = input.readBoolean();
			this.outgoingMessageAccentColor = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ThemeSettings.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ThemeSettings.CONSTRUCTOR);
			output.writeInt(this.accentColor);
			if (this.background == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.background.serialize(output);
			}
			if (this.outgoingMessageFill == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.outgoingMessageFill.serialize(output);
			}
			output.writeBoolean(this.animateOutgoingMessageFill);
			output.writeInt(this.outgoingMessageAccentColor);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ThemeSettings themeSettings = (ThemeSettings) o;
			if (this.accentColor != themeSettings.accentColor) {
				return false;
			}
			if (!Objects.equals(this.background, themeSettings.background)) {
				return false;
			}
			if (!Objects.equals(this.outgoingMessageFill, themeSettings.outgoingMessageFill)) {
				return false;
			}
			if (this.animateOutgoingMessageFill != themeSettings.animateOutgoingMessageFill) {
				return false;
			}
			if (this.outgoingMessageAccentColor != themeSettings.outgoingMessageAccentColor) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.accentColor);
			result = result * 31 + (this.background == null ? 0 : this.background.hashCode());
			result = result * 31 + (this.outgoingMessageFill == null ? 0 : this.outgoingMessageFill.hashCode());
			return result;
		}
	}

	/**
	 * Represents a thumbnail.
	**/
	public static final class Thumbnail extends Object {


		/**
		 * Thumbnail format.
		**/
		public ThumbnailFormat format;

		/**
		 * Thumbnail width.
		**/
		public int width;

		/**
		 * Thumbnail height.
		**/
		public int height;

		/**
		 * The thumbnail.
		**/
		public File file;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1243275371;

		/**
		 * Represents a thumbnail.
		**/
		public Thumbnail() {}

		/**
		 * Represents a thumbnail.
		 *
		 * @param format Thumbnail format.
		 * @param width Thumbnail width.
		 * @param height Thumbnail height.
		 * @param file The thumbnail.
		**/
		public Thumbnail(ThumbnailFormat format, int width, int height, File file) {
			this.format = format;
			this.width = width;
			this.height = height;
			this.file = file;
		}

		/**
		 * Represents a thumbnail.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public Thumbnail(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ThumbnailFormatJpeg.CONSTRUCTOR: this.format = new ThumbnailFormatJpeg(input); break;
					case ThumbnailFormatGif.CONSTRUCTOR: this.format = new ThumbnailFormatGif(input); break;
					case ThumbnailFormatMpeg4.CONSTRUCTOR: this.format = new ThumbnailFormatMpeg4(input); break;
					case ThumbnailFormatPng.CONSTRUCTOR: this.format = new ThumbnailFormatPng(input); break;
					case ThumbnailFormatTgs.CONSTRUCTOR: this.format = new ThumbnailFormatTgs(input); break;
					case ThumbnailFormatWebm.CONSTRUCTOR: this.format = new ThumbnailFormatWebm(input); break;
					case ThumbnailFormatWebp.CONSTRUCTOR: this.format = new ThumbnailFormatWebp(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.width = input.readInt();
			this.height = input.readInt();
			if (input.readBoolean()) {
				if (File.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.file = new File(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return Thumbnail.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(Thumbnail.CONSTRUCTOR);
			if (this.format == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.format.serialize(output);
			}
			output.writeInt(this.width);
			output.writeInt(this.height);
			if (this.file == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.file.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			Thumbnail thumbnail = (Thumbnail) o;
			if (!Objects.equals(this.format, thumbnail.format)) {
				return false;
			}
			if (this.width != thumbnail.width) {
				return false;
			}
			if (this.height != thumbnail.height) {
				return false;
			}
			if (!Objects.equals(this.file, thumbnail.file)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.width);
			result = result * 31 + (this.format == null ? 0 : this.format.hashCode());
			result = result * 31 + (this.file == null ? 0 : this.file.hashCode());
			return result;
		}
	}

	/**
	 * The thumbnail is in JPEG format.
	**/
	public static final class ThumbnailFormatJpeg extends ThumbnailFormat {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -653503352;

		/**
		 * The thumbnail is in JPEG format.
		**/
		public ThumbnailFormatJpeg() {}

		/**
		 * The thumbnail is in JPEG format.
		 *
		**/

		/**
		 * The thumbnail is in JPEG format.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ThumbnailFormatJpeg(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ThumbnailFormatJpeg.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ThumbnailFormatJpeg.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ThumbnailFormatJpeg.CONSTRUCTOR;
		}
	}

	/**
	 * The thumbnail is in static GIF format. It will be used only for some
	 * bot inline results.
	**/
	public static final class ThumbnailFormatGif extends ThumbnailFormat {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1252205962;

		/**
		 * The thumbnail is in static GIF format. It will be used only for some bot inline results.
		**/
		public ThumbnailFormatGif() {}

		/**
		 * The thumbnail is in static GIF format. It will be used only for some bot inline results.
		 *
		**/

		/**
		 * The thumbnail is in static GIF format. It will be used only for some bot inline results.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ThumbnailFormatGif(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ThumbnailFormatGif.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ThumbnailFormatGif.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ThumbnailFormatGif.CONSTRUCTOR;
		}
	}

	/**
	 * The thumbnail is in MPEG4 format. It will be used only for some
	 * animations and videos.
	**/
	public static final class ThumbnailFormatMpeg4 extends ThumbnailFormat {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 278616062;

		/**
		 * The thumbnail is in MPEG4 format. It will be used only for some animations and videos.
		**/
		public ThumbnailFormatMpeg4() {}

		/**
		 * The thumbnail is in MPEG4 format. It will be used only for some animations and videos.
		 *
		**/

		/**
		 * The thumbnail is in MPEG4 format. It will be used only for some animations and videos.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ThumbnailFormatMpeg4(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ThumbnailFormatMpeg4.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ThumbnailFormatMpeg4.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ThumbnailFormatMpeg4.CONSTRUCTOR;
		}
	}

	/**
	 * The thumbnail is in PNG format. It will be used only for background
	 * patterns.
	**/
	public static final class ThumbnailFormatPng extends ThumbnailFormat {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1577490421;

		/**
		 * The thumbnail is in PNG format. It will be used only for background patterns.
		**/
		public ThumbnailFormatPng() {}

		/**
		 * The thumbnail is in PNG format. It will be used only for background patterns.
		 *
		**/

		/**
		 * The thumbnail is in PNG format. It will be used only for background patterns.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ThumbnailFormatPng(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ThumbnailFormatPng.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ThumbnailFormatPng.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ThumbnailFormatPng.CONSTRUCTOR;
		}
	}

	/**
	 * The thumbnail is in TGS format. It will be used only for TGS sticker
	 * sets.
	**/
	public static final class ThumbnailFormatTgs extends ThumbnailFormat {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1315522642;

		/**
		 * The thumbnail is in TGS format. It will be used only for TGS sticker sets.
		**/
		public ThumbnailFormatTgs() {}

		/**
		 * The thumbnail is in TGS format. It will be used only for TGS sticker sets.
		 *
		**/

		/**
		 * The thumbnail is in TGS format. It will be used only for TGS sticker sets.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ThumbnailFormatTgs(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ThumbnailFormatTgs.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ThumbnailFormatTgs.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ThumbnailFormatTgs.CONSTRUCTOR;
		}
	}

	/**
	 * The thumbnail is in WEBM format. It will be used only for WEBM
	 * sticker sets.
	**/
	public static final class ThumbnailFormatWebm extends ThumbnailFormat {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -660084953;

		/**
		 * The thumbnail is in WEBM format. It will be used only for WEBM sticker sets.
		**/
		public ThumbnailFormatWebm() {}

		/**
		 * The thumbnail is in WEBM format. It will be used only for WEBM sticker sets.
		 *
		**/

		/**
		 * The thumbnail is in WEBM format. It will be used only for WEBM sticker sets.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ThumbnailFormatWebm(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ThumbnailFormatWebm.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ThumbnailFormatWebm.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ThumbnailFormatWebm.CONSTRUCTOR;
		}
	}

	/**
	 * The thumbnail is in WEBP format. It will be used only for some
	 * stickers.
	**/
	public static final class ThumbnailFormatWebp extends ThumbnailFormat {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -53588974;

		/**
		 * The thumbnail is in WEBP format. It will be used only for some stickers.
		**/
		public ThumbnailFormatWebp() {}

		/**
		 * The thumbnail is in WEBP format. It will be used only for some stickers.
		 *
		**/

		/**
		 * The thumbnail is in WEBP format. It will be used only for some stickers.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ThumbnailFormatWebp(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ThumbnailFormatWebp.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ThumbnailFormatWebp.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ThumbnailFormatWebp.CONSTRUCTOR;
		}
	}

	/**
	 * A category containing frequently used private chats with non-bot
	 * users.
	**/
	public static final class TopChatCategoryUsers extends TopChatCategory {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1026706816;

		/**
		 * A category containing frequently used private chats with non-bot users.
		**/
		public TopChatCategoryUsers() {}

		/**
		 * A category containing frequently used private chats with non-bot users.
		 *
		**/

		/**
		 * A category containing frequently used private chats with non-bot users.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TopChatCategoryUsers(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TopChatCategoryUsers.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TopChatCategoryUsers.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return TopChatCategoryUsers.CONSTRUCTOR;
		}
	}

	/**
	 * A category containing frequently used private chats with bot users.
	**/
	public static final class TopChatCategoryBots extends TopChatCategory {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1577129195;

		/**
		 * A category containing frequently used private chats with bot users.
		**/
		public TopChatCategoryBots() {}

		/**
		 * A category containing frequently used private chats with bot users.
		 *
		**/

		/**
		 * A category containing frequently used private chats with bot users.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TopChatCategoryBots(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TopChatCategoryBots.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TopChatCategoryBots.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return TopChatCategoryBots.CONSTRUCTOR;
		}
	}

	/**
	 * A category containing frequently used basic groups and supergroups.
	**/
	public static final class TopChatCategoryGroups extends TopChatCategory {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1530056846;

		/**
		 * A category containing frequently used basic groups and supergroups.
		**/
		public TopChatCategoryGroups() {}

		/**
		 * A category containing frequently used basic groups and supergroups.
		 *
		**/

		/**
		 * A category containing frequently used basic groups and supergroups.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TopChatCategoryGroups(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TopChatCategoryGroups.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TopChatCategoryGroups.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return TopChatCategoryGroups.CONSTRUCTOR;
		}
	}

	/**
	 * A category containing frequently used channels.
	**/
	public static final class TopChatCategoryChannels extends TopChatCategory {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -500825885;

		/**
		 * A category containing frequently used channels.
		**/
		public TopChatCategoryChannels() {}

		/**
		 * A category containing frequently used channels.
		 *
		**/

		/**
		 * A category containing frequently used channels.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TopChatCategoryChannels(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TopChatCategoryChannels.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TopChatCategoryChannels.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return TopChatCategoryChannels.CONSTRUCTOR;
		}
	}

	/**
	 * A category containing frequently used chats with inline bots sorted
	 * by their usage in inline mode.
	**/
	public static final class TopChatCategoryInlineBots extends TopChatCategory {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 377023356;

		/**
		 * A category containing frequently used chats with inline bots sorted by their usage in inline mode.
		**/
		public TopChatCategoryInlineBots() {}

		/**
		 * A category containing frequently used chats with inline bots sorted by their usage in inline mode.
		 *
		**/

		/**
		 * A category containing frequently used chats with inline bots sorted by their usage in inline mode.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TopChatCategoryInlineBots(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TopChatCategoryInlineBots.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TopChatCategoryInlineBots.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return TopChatCategoryInlineBots.CONSTRUCTOR;
		}
	}

	/**
	 * A category containing frequently used chats used for calls.
	**/
	public static final class TopChatCategoryCalls extends TopChatCategory {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 356208861;

		/**
		 * A category containing frequently used chats used for calls.
		**/
		public TopChatCategoryCalls() {}

		/**
		 * A category containing frequently used chats used for calls.
		 *
		**/

		/**
		 * A category containing frequently used chats used for calls.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TopChatCategoryCalls(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TopChatCategoryCalls.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TopChatCategoryCalls.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return TopChatCategoryCalls.CONSTRUCTOR;
		}
	}

	/**
	 * A category containing frequently used chats used to forward messages.
	**/
	public static final class TopChatCategoryForwardChats extends TopChatCategory {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1695922133;

		/**
		 * A category containing frequently used chats used to forward messages.
		**/
		public TopChatCategoryForwardChats() {}

		/**
		 * A category containing frequently used chats used to forward messages.
		 *
		**/

		/**
		 * A category containing frequently used chats used to forward messages.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TopChatCategoryForwardChats(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TopChatCategoryForwardChats.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TopChatCategoryForwardChats.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return TopChatCategoryForwardChats.CONSTRUCTOR;
		}
	}

	/**
	 * Represents a list of trending sticker sets.
	**/
	public static final class TrendingStickerSets extends Object {


		/**
		 * Approximate total number of trending sticker sets.
		**/
		public int totalCount;

		/**
		 * List of trending sticker sets.
		**/
		public StickerSetInfo[] sets;

		/**
		 * True, if the list contains sticker sets with premium stickers.
		**/
		public boolean isPremium;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 41028940;

		/**
		 * Represents a list of trending sticker sets.
		**/
		public TrendingStickerSets() {}

		/**
		 * Represents a list of trending sticker sets.
		 *
		 * @param totalCount Approximate total number of trending sticker sets.
		 * @param sets List of trending sticker sets.
		 * @param isPremium True, if the list contains sticker sets with premium stickers.
		**/
		public TrendingStickerSets(int totalCount, StickerSetInfo[] sets, boolean isPremium) {
			this.totalCount = totalCount;
			this.sets = sets;
			this.isPremium = isPremium;
		}

		/**
		 * Represents a list of trending sticker sets.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TrendingStickerSets(DataInput input) throws IOException {
			this.totalCount = input.readInt();
			if (input.readBoolean()) {
				this.sets = new StickerSetInfo[input.readInt()];
				for (int i = 0; i < this.sets.length; i++) {
					if (StickerSetInfo.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.sets[i] = new StickerSetInfo(input);
				}
			}
			this.isPremium = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TrendingStickerSets.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TrendingStickerSets.CONSTRUCTOR);
			output.writeInt(this.totalCount);
			if (this.sets == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.sets.length);
				for (int i = 0; i < this.sets.length; i++) {
					this.sets[i].serialize(output);
				}
			}
			output.writeBoolean(this.isPremium);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			TrendingStickerSets trendingStickerSets = (TrendingStickerSets) o;
			if (this.totalCount != trendingStickerSets.totalCount) {
				return false;
			}
			if (!Arrays.equals(this.sets, trendingStickerSets.sets)) {
				return false;
			}
			if (this.isPremium != trendingStickerSets.isPremium) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.totalCount);
			result = result * 31 + (Arrays.hashCode(this.sets));
			return result;
		}
	}

	/**
	 * Contains information about an unread reaction to a message.
	**/
	public static final class UnreadReaction extends Object {


		/**
		 * Type of the reaction.
		**/
		public ReactionType type;

		/**
		 * Identifier of the sender, added the reaction.
		**/
		public MessageSender senderId;

		/**
		 * True, if the reaction was added with a big animation.
		**/
		public boolean isBig;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1940178046;

		/**
		 * Contains information about an unread reaction to a message.
		**/
		public UnreadReaction() {}

		/**
		 * Contains information about an unread reaction to a message.
		 *
		 * @param type Type of the reaction.
		 * @param senderId Identifier of the sender, added the reaction.
		 * @param isBig True, if the reaction was added with a big animation.
		**/
		public UnreadReaction(ReactionType type, MessageSender senderId, boolean isBig) {
			this.type = type;
			this.senderId = senderId;
			this.isBig = isBig;
		}

		/**
		 * Contains information about an unread reaction to a message.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UnreadReaction(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ReactionTypeEmoji.CONSTRUCTOR: this.type = new ReactionTypeEmoji(input); break;
					case ReactionTypeCustomEmoji.CONSTRUCTOR: this.type = new ReactionTypeCustomEmoji(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case MessageSenderUser.CONSTRUCTOR: this.senderId = new MessageSenderUser(input); break;
					case MessageSenderChat.CONSTRUCTOR: this.senderId = new MessageSenderChat(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.isBig = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UnreadReaction.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UnreadReaction.CONSTRUCTOR);
			if (this.type == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.type.serialize(output);
			}
			if (this.senderId == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.senderId.serialize(output);
			}
			output.writeBoolean(this.isBig);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UnreadReaction unreadReaction = (UnreadReaction) o;
			if (!Objects.equals(this.type, unreadReaction.type)) {
				return false;
			}
			if (!Objects.equals(this.senderId, unreadReaction.senderId)) {
				return false;
			}
			if (this.isBig != unreadReaction.isBig) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isBig);
			result = result * 31 + (this.type == null ? 0 : this.type.hashCode());
			result = result * 31 + (this.senderId == null ? 0 : this.senderId.hashCode());
			return result;
		}
	}

	/**
	 * The user authorization state has changed.
	**/
	public static final class UpdateAuthorizationState extends Update {


		/**
		 * New authorization state.
		**/
		public AuthorizationState authorizationState;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1622347490;

		/**
		 * The user authorization state has changed.
		**/
		public UpdateAuthorizationState() {}

		/**
		 * The user authorization state has changed.
		 *
		 * @param authorizationState New authorization state.
		**/
		public UpdateAuthorizationState(AuthorizationState authorizationState) {
			this.authorizationState = authorizationState;
		}

		/**
		 * The user authorization state has changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateAuthorizationState(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case AuthorizationStateWaitTdlibParameters.CONSTRUCTOR: this.authorizationState = new AuthorizationStateWaitTdlibParameters(input); break;
					case AuthorizationStateWaitPhoneNumber.CONSTRUCTOR: this.authorizationState = new AuthorizationStateWaitPhoneNumber(input); break;
					case AuthorizationStateWaitEmailAddress.CONSTRUCTOR: this.authorizationState = new AuthorizationStateWaitEmailAddress(input); break;
					case AuthorizationStateWaitEmailCode.CONSTRUCTOR: this.authorizationState = new AuthorizationStateWaitEmailCode(input); break;
					case AuthorizationStateWaitCode.CONSTRUCTOR: this.authorizationState = new AuthorizationStateWaitCode(input); break;
					case AuthorizationStateWaitOtherDeviceConfirmation.CONSTRUCTOR: this.authorizationState = new AuthorizationStateWaitOtherDeviceConfirmation(input); break;
					case AuthorizationStateWaitRegistration.CONSTRUCTOR: this.authorizationState = new AuthorizationStateWaitRegistration(input); break;
					case AuthorizationStateWaitPassword.CONSTRUCTOR: this.authorizationState = new AuthorizationStateWaitPassword(input); break;
					case AuthorizationStateReady.CONSTRUCTOR: this.authorizationState = new AuthorizationStateReady(input); break;
					case AuthorizationStateLoggingOut.CONSTRUCTOR: this.authorizationState = new AuthorizationStateLoggingOut(input); break;
					case AuthorizationStateClosing.CONSTRUCTOR: this.authorizationState = new AuthorizationStateClosing(input); break;
					case AuthorizationStateClosed.CONSTRUCTOR: this.authorizationState = new AuthorizationStateClosed(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateAuthorizationState.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateAuthorizationState.CONSTRUCTOR);
			if (this.authorizationState == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.authorizationState.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateAuthorizationState updateAuthorizationState = (UpdateAuthorizationState) o;
			if (!Objects.equals(this.authorizationState, updateAuthorizationState.authorizationState)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.authorizationState == null ? 0 : this.authorizationState.hashCode();
		}
	}

	/**
	 * A new message was received; can also be an outgoing message.
	**/
	public static final class UpdateNewMessage extends Update {


		/**
		 * The new message.
		**/
		public Message message;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -563105266;

		/**
		 * A new message was received; can also be an outgoing message.
		**/
		public UpdateNewMessage() {}

		/**
		 * A new message was received; can also be an outgoing message.
		 *
		 * @param message The new message.
		**/
		public UpdateNewMessage(Message message) {
			this.message = message;
		}

		/**
		 * A new message was received; can also be an outgoing message.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateNewMessage(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Message.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.message = new Message(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateNewMessage.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateNewMessage.CONSTRUCTOR);
			if (this.message == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.message.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateNewMessage updateNewMessage = (UpdateNewMessage) o;
			if (!Objects.equals(this.message, updateNewMessage.message)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.message == null ? 0 : this.message.hashCode();
		}
	}

	/**
	 * A request to send a message has reached the Telegram server. This
	 * doesn&#039;t mean that the message will be sent successfully or even
	 * that the send message request will be processed. This update will be
	 * sent only if the option &quot;use_quick_ack&quot; is set to true.
	 * This update may be sent multiple times for the same message.
	**/
	public static final class UpdateMessageSendAcknowledged extends Update {


		/**
		 * The chat identifier of the sent message.
		**/
		public long chatId;

		/**
		 * A temporary message identifier.
		**/
		public long messageId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1302843961;

		/**
		 * A request to send a message has reached the Telegram server. This doesn&#039;t mean that the message will be sent successfully or even that the send message request will be processed. This update will be sent only if the option &quot;use_quick_ack&quot; is set to true. This update may be sent multiple times for the same message.
		**/
		public UpdateMessageSendAcknowledged() {}

		/**
		 * A request to send a message has reached the Telegram server. This doesn&#039;t mean that the message will be sent successfully or even that the send message request will be processed. This update will be sent only if the option &quot;use_quick_ack&quot; is set to true. This update may be sent multiple times for the same message.
		 *
		 * @param chatId The chat identifier of the sent message.
		 * @param messageId A temporary message identifier.
		**/
		public UpdateMessageSendAcknowledged(long chatId, long messageId) {
			this.chatId = chatId;
			this.messageId = messageId;
		}

		/**
		 * A request to send a message has reached the Telegram server. This doesn&#039;t mean that the message will be sent successfully or even that the send message request will be processed. This update will be sent only if the option &quot;use_quick_ack&quot; is set to true. This update may be sent multiple times for the same message.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateMessageSendAcknowledged(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateMessageSendAcknowledged.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateMessageSendAcknowledged.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateMessageSendAcknowledged updateMessageSendAcknowledged = (UpdateMessageSendAcknowledged) o;
			if (this.chatId != updateMessageSendAcknowledged.chatId) {
				return false;
			}
			if (this.messageId != updateMessageSendAcknowledged.messageId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * A message has been successfully sent.
	**/
	public static final class UpdateMessageSendSucceeded extends Update {


		/**
		 * The sent message. Usually only the message identifier, date, and content are changed, but almost all other fields can also change.
		**/
		public Message message;

		/**
		 * The previous temporary message identifier.
		**/
		public long oldMessageId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1815715197;

		/**
		 * A message has been successfully sent.
		**/
		public UpdateMessageSendSucceeded() {}

		/**
		 * A message has been successfully sent.
		 *
		 * @param message The sent message. Usually only the message identifier, date, and content are changed, but almost all other fields can also change.
		 * @param oldMessageId The previous temporary message identifier.
		**/
		public UpdateMessageSendSucceeded(Message message, long oldMessageId) {
			this.message = message;
			this.oldMessageId = oldMessageId;
		}

		/**
		 * A message has been successfully sent.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateMessageSendSucceeded(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Message.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.message = new Message(input);
			}
			this.oldMessageId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateMessageSendSucceeded.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateMessageSendSucceeded.CONSTRUCTOR);
			if (this.message == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.message.serialize(output);
			}
			output.writeLong(this.oldMessageId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateMessageSendSucceeded updateMessageSendSucceeded = (UpdateMessageSendSucceeded) o;
			if (!Objects.equals(this.message, updateMessageSendSucceeded.message)) {
				return false;
			}
			if (this.oldMessageId != updateMessageSendSucceeded.oldMessageId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.oldMessageId);
			result = result * 31 + (this.message == null ? 0 : this.message.hashCode());
			return result;
		}
	}

	/**
	 * A message failed to send. Be aware that some messages being sent can
	 * be irrecoverably deleted, in which case updateDeleteMessages will be
	 * received instead of this update.
	**/
	public static final class UpdateMessageSendFailed extends Update {


		/**
		 * The failed to send message.
		**/
		public Message message;

		/**
		 * The previous temporary message identifier.
		**/
		public long oldMessageId;

		/**
		 * An error code.
		**/
		public int errorCode;

		/**
		 * Error message.
		**/
		public String errorMessage;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1032335779;

		/**
		 * A message failed to send. Be aware that some messages being sent can be irrecoverably deleted, in which case updateDeleteMessages will be received instead of this update.
		**/
		public UpdateMessageSendFailed() {}

		/**
		 * A message failed to send. Be aware that some messages being sent can be irrecoverably deleted, in which case updateDeleteMessages will be received instead of this update.
		 *
		 * @param message The failed to send message.
		 * @param oldMessageId The previous temporary message identifier.
		 * @param errorCode An error code.
		 * @param errorMessage Error message.
		**/
		public UpdateMessageSendFailed(Message message,
				long oldMessageId,
				int errorCode,
				String errorMessage) {
			this.message = message;
			this.oldMessageId = oldMessageId;
			this.errorCode = errorCode;
			this.errorMessage = errorMessage;
		}

		/**
		 * A message failed to send. Be aware that some messages being sent can be irrecoverably deleted, in which case updateDeleteMessages will be received instead of this update.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateMessageSendFailed(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Message.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.message = new Message(input);
			}
			this.oldMessageId = input.readLong();
			this.errorCode = input.readInt();
			if (input.readBoolean()) {
				byte[] errorMessageTmp = new byte[input.readInt()];
				input.readFully(errorMessageTmp);
				this.errorMessage = new String(errorMessageTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateMessageSendFailed.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateMessageSendFailed.CONSTRUCTOR);
			if (this.message == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.message.serialize(output);
			}
			output.writeLong(this.oldMessageId);
			output.writeInt(this.errorCode);
			if (this.errorMessage == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] errorMessageTmp = this.errorMessage.getBytes(StandardCharsets.UTF_8);
				output.writeInt(errorMessageTmp.length);
				output.write(errorMessageTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateMessageSendFailed updateMessageSendFailed = (UpdateMessageSendFailed) o;
			if (!Objects.equals(this.message, updateMessageSendFailed.message)) {
				return false;
			}
			if (this.oldMessageId != updateMessageSendFailed.oldMessageId) {
				return false;
			}
			if (this.errorCode != updateMessageSendFailed.errorCode) {
				return false;
			}
			if (this.errorMessage != updateMessageSendFailed.errorMessage) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.oldMessageId);
			result = result * 31 + (this.message == null ? 0 : this.message.hashCode());
			result = result * 31 + (this.errorMessage == null ? 0 : this.errorMessage.hashCode());
			return result;
		}
	}

	/**
	 * The message content has changed.
	**/
	public static final class UpdateMessageContent extends Update {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Message identifier.
		**/
		public long messageId;

		/**
		 * New message content.
		**/
		public MessageContent newContent;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 506903332;

		/**
		 * The message content has changed.
		**/
		public UpdateMessageContent() {}

		/**
		 * The message content has changed.
		 *
		 * @param chatId Chat identifier.
		 * @param messageId Message identifier.
		 * @param newContent New message content.
		**/
		public UpdateMessageContent(long chatId, long messageId, MessageContent newContent) {
			this.chatId = chatId;
			this.messageId = messageId;
			this.newContent = newContent;
		}

		/**
		 * The message content has changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateMessageContent(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case MessageText.CONSTRUCTOR: this.newContent = new MessageText(input); break;
					case MessageAnimation.CONSTRUCTOR: this.newContent = new MessageAnimation(input); break;
					case MessageAudio.CONSTRUCTOR: this.newContent = new MessageAudio(input); break;
					case MessageDocument.CONSTRUCTOR: this.newContent = new MessageDocument(input); break;
					case MessagePhoto.CONSTRUCTOR: this.newContent = new MessagePhoto(input); break;
					case MessageExpiredPhoto.CONSTRUCTOR: this.newContent = new MessageExpiredPhoto(input); break;
					case MessageSticker.CONSTRUCTOR: this.newContent = new MessageSticker(input); break;
					case MessageVideo.CONSTRUCTOR: this.newContent = new MessageVideo(input); break;
					case MessageExpiredVideo.CONSTRUCTOR: this.newContent = new MessageExpiredVideo(input); break;
					case MessageVideoNote.CONSTRUCTOR: this.newContent = new MessageVideoNote(input); break;
					case MessageVoiceNote.CONSTRUCTOR: this.newContent = new MessageVoiceNote(input); break;
					case MessageLocation.CONSTRUCTOR: this.newContent = new MessageLocation(input); break;
					case MessageVenue.CONSTRUCTOR: this.newContent = new MessageVenue(input); break;
					case MessageContact.CONSTRUCTOR: this.newContent = new MessageContact(input); break;
					case MessageAnimatedEmoji.CONSTRUCTOR: this.newContent = new MessageAnimatedEmoji(input); break;
					case MessageDice.CONSTRUCTOR: this.newContent = new MessageDice(input); break;
					case MessageGame.CONSTRUCTOR: this.newContent = new MessageGame(input); break;
					case MessagePoll.CONSTRUCTOR: this.newContent = new MessagePoll(input); break;
					case MessageInvoice.CONSTRUCTOR: this.newContent = new MessageInvoice(input); break;
					case MessageCall.CONSTRUCTOR: this.newContent = new MessageCall(input); break;
					case MessageVideoChatScheduled.CONSTRUCTOR: this.newContent = new MessageVideoChatScheduled(input); break;
					case MessageVideoChatStarted.CONSTRUCTOR: this.newContent = new MessageVideoChatStarted(input); break;
					case MessageVideoChatEnded.CONSTRUCTOR: this.newContent = new MessageVideoChatEnded(input); break;
					case MessageInviteVideoChatParticipants.CONSTRUCTOR: this.newContent = new MessageInviteVideoChatParticipants(input); break;
					case MessageBasicGroupChatCreate.CONSTRUCTOR: this.newContent = new MessageBasicGroupChatCreate(input); break;
					case MessageSupergroupChatCreate.CONSTRUCTOR: this.newContent = new MessageSupergroupChatCreate(input); break;
					case MessageChatChangeTitle.CONSTRUCTOR: this.newContent = new MessageChatChangeTitle(input); break;
					case MessageChatChangePhoto.CONSTRUCTOR: this.newContent = new MessageChatChangePhoto(input); break;
					case MessageChatDeletePhoto.CONSTRUCTOR: this.newContent = new MessageChatDeletePhoto(input); break;
					case MessageChatAddMembers.CONSTRUCTOR: this.newContent = new MessageChatAddMembers(input); break;
					case MessageChatJoinByLink.CONSTRUCTOR: this.newContent = new MessageChatJoinByLink(input); break;
					case MessageChatJoinByRequest.CONSTRUCTOR: this.newContent = new MessageChatJoinByRequest(input); break;
					case MessageChatDeleteMember.CONSTRUCTOR: this.newContent = new MessageChatDeleteMember(input); break;
					case MessageChatUpgradeTo.CONSTRUCTOR: this.newContent = new MessageChatUpgradeTo(input); break;
					case MessageChatUpgradeFrom.CONSTRUCTOR: this.newContent = new MessageChatUpgradeFrom(input); break;
					case MessagePinMessage.CONSTRUCTOR: this.newContent = new MessagePinMessage(input); break;
					case MessageScreenshotTaken.CONSTRUCTOR: this.newContent = new MessageScreenshotTaken(input); break;
					case MessageChatSetBackground.CONSTRUCTOR: this.newContent = new MessageChatSetBackground(input); break;
					case MessageChatSetTheme.CONSTRUCTOR: this.newContent = new MessageChatSetTheme(input); break;
					case MessageChatSetMessageAutoDeleteTime.CONSTRUCTOR: this.newContent = new MessageChatSetMessageAutoDeleteTime(input); break;
					case MessageForumTopicCreated.CONSTRUCTOR: this.newContent = new MessageForumTopicCreated(input); break;
					case MessageForumTopicEdited.CONSTRUCTOR: this.newContent = new MessageForumTopicEdited(input); break;
					case MessageForumTopicIsClosedToggled.CONSTRUCTOR: this.newContent = new MessageForumTopicIsClosedToggled(input); break;
					case MessageForumTopicIsHiddenToggled.CONSTRUCTOR: this.newContent = new MessageForumTopicIsHiddenToggled(input); break;
					case MessageSuggestProfilePhoto.CONSTRUCTOR: this.newContent = new MessageSuggestProfilePhoto(input); break;
					case MessageCustomServiceAction.CONSTRUCTOR: this.newContent = new MessageCustomServiceAction(input); break;
					case MessageGameScore.CONSTRUCTOR: this.newContent = new MessageGameScore(input); break;
					case MessagePaymentSuccessful.CONSTRUCTOR: this.newContent = new MessagePaymentSuccessful(input); break;
					case MessagePaymentSuccessfulBot.CONSTRUCTOR: this.newContent = new MessagePaymentSuccessfulBot(input); break;
					case MessageGiftedPremium.CONSTRUCTOR: this.newContent = new MessageGiftedPremium(input); break;
					case MessageContactRegistered.CONSTRUCTOR: this.newContent = new MessageContactRegistered(input); break;
					case MessageUserShared.CONSTRUCTOR: this.newContent = new MessageUserShared(input); break;
					case MessageChatShared.CONSTRUCTOR: this.newContent = new MessageChatShared(input); break;
					case MessageWebsiteConnected.CONSTRUCTOR: this.newContent = new MessageWebsiteConnected(input); break;
					case MessageBotWriteAccessAllowed.CONSTRUCTOR: this.newContent = new MessageBotWriteAccessAllowed(input); break;
					case MessageWebAppDataSent.CONSTRUCTOR: this.newContent = new MessageWebAppDataSent(input); break;
					case MessageWebAppDataReceived.CONSTRUCTOR: this.newContent = new MessageWebAppDataReceived(input); break;
					case MessagePassportDataSent.CONSTRUCTOR: this.newContent = new MessagePassportDataSent(input); break;
					case MessagePassportDataReceived.CONSTRUCTOR: this.newContent = new MessagePassportDataReceived(input); break;
					case MessageProximityAlertTriggered.CONSTRUCTOR: this.newContent = new MessageProximityAlertTriggered(input); break;
					case MessageUnsupported.CONSTRUCTOR: this.newContent = new MessageUnsupported(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateMessageContent.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateMessageContent.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
			if (this.newContent == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.newContent.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateMessageContent updateMessageContent = (UpdateMessageContent) o;
			if (this.chatId != updateMessageContent.chatId) {
				return false;
			}
			if (this.messageId != updateMessageContent.messageId) {
				return false;
			}
			if (!Objects.equals(this.newContent, updateMessageContent.newContent)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.newContent == null ? 0 : this.newContent.hashCode());
			return result;
		}
	}

	/**
	 * A message was edited. Changes in the message content will come in a
	 * separate updateMessageContent.
	**/
	public static final class UpdateMessageEdited extends Update {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Message identifier.
		**/
		public long messageId;

		/**
		 * Point in time (Unix timestamp) when the message was edited.
		**/
		public int editDate;

		/**
		 * New message reply markup; may be null.
		**/
		public ReplyMarkup replyMarkup;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -559545626;

		/**
		 * A message was edited. Changes in the message content will come in a separate updateMessageContent.
		**/
		public UpdateMessageEdited() {}

		/**
		 * A message was edited. Changes in the message content will come in a separate updateMessageContent.
		 *
		 * @param chatId Chat identifier.
		 * @param messageId Message identifier.
		 * @param editDate Point in time (Unix timestamp) when the message was edited.
		 * @param replyMarkup New message reply markup; may be null.
		**/
		public UpdateMessageEdited(long chatId,
				long messageId,
				int editDate,
				ReplyMarkup replyMarkup) {
			this.chatId = chatId;
			this.messageId = messageId;
			this.editDate = editDate;
			this.replyMarkup = replyMarkup;
		}

		/**
		 * A message was edited. Changes in the message content will come in a separate updateMessageContent.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateMessageEdited(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
			this.editDate = input.readInt();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ReplyMarkupRemoveKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupRemoveKeyboard(input); break;
					case ReplyMarkupForceReply.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupForceReply(input); break;
					case ReplyMarkupShowKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupShowKeyboard(input); break;
					case ReplyMarkupInlineKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupInlineKeyboard(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateMessageEdited.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateMessageEdited.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
			output.writeInt(this.editDate);
			if (this.replyMarkup == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.replyMarkup.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateMessageEdited updateMessageEdited = (UpdateMessageEdited) o;
			if (this.chatId != updateMessageEdited.chatId) {
				return false;
			}
			if (this.messageId != updateMessageEdited.messageId) {
				return false;
			}
			if (this.editDate != updateMessageEdited.editDate) {
				return false;
			}
			if (!Objects.equals(this.replyMarkup, updateMessageEdited.replyMarkup)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.replyMarkup == null ? 0 : this.replyMarkup.hashCode());
			return result;
		}
	}

	/**
	 * The message pinned state was changed.
	**/
	public static final class UpdateMessageIsPinned extends Update {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * The message identifier.
		**/
		public long messageId;

		/**
		 * True, if the message is pinned.
		**/
		public boolean isPinned;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1102848829;

		/**
		 * The message pinned state was changed.
		**/
		public UpdateMessageIsPinned() {}

		/**
		 * The message pinned state was changed.
		 *
		 * @param chatId Chat identifier.
		 * @param messageId The message identifier.
		 * @param isPinned True, if the message is pinned.
		**/
		public UpdateMessageIsPinned(long chatId, long messageId, boolean isPinned) {
			this.chatId = chatId;
			this.messageId = messageId;
			this.isPinned = isPinned;
		}

		/**
		 * The message pinned state was changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateMessageIsPinned(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
			this.isPinned = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateMessageIsPinned.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateMessageIsPinned.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
			output.writeBoolean(this.isPinned);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateMessageIsPinned updateMessageIsPinned = (UpdateMessageIsPinned) o;
			if (this.chatId != updateMessageIsPinned.chatId) {
				return false;
			}
			if (this.messageId != updateMessageIsPinned.messageId) {
				return false;
			}
			if (this.isPinned != updateMessageIsPinned.isPinned) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * The information about interactions with a message has changed.
	**/
	public static final class UpdateMessageInteractionInfo extends Update {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Message identifier.
		**/
		public long messageId;

		/**
		 * New information about interactions with the message; may be null.
		**/
		public MessageInteractionInfo interactionInfo;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1417659394;

		/**
		 * The information about interactions with a message has changed.
		**/
		public UpdateMessageInteractionInfo() {}

		/**
		 * The information about interactions with a message has changed.
		 *
		 * @param chatId Chat identifier.
		 * @param messageId Message identifier.
		 * @param interactionInfo New information about interactions with the message; may be null.
		**/
		public UpdateMessageInteractionInfo(long chatId,
				long messageId,
				MessageInteractionInfo interactionInfo) {
			this.chatId = chatId;
			this.messageId = messageId;
			this.interactionInfo = interactionInfo;
		}

		/**
		 * The information about interactions with a message has changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateMessageInteractionInfo(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
			if (input.readBoolean()) {
				if (MessageInteractionInfo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.interactionInfo = new MessageInteractionInfo(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateMessageInteractionInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateMessageInteractionInfo.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
			if (this.interactionInfo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.interactionInfo.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateMessageInteractionInfo updateMessageInteractionInfo = (UpdateMessageInteractionInfo) o;
			if (this.chatId != updateMessageInteractionInfo.chatId) {
				return false;
			}
			if (this.messageId != updateMessageInteractionInfo.messageId) {
				return false;
			}
			if (!Objects.equals(this.interactionInfo, updateMessageInteractionInfo.interactionInfo)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.interactionInfo == null ? 0 : this.interactionInfo.hashCode());
			return result;
		}
	}

	/**
	 * The message content was opened. Updates voice note messages to
	 * &quot;listened&quot;, video note messages to &quot;viewed&quot; and
	 * starts the self-destruct timer.
	**/
	public static final class UpdateMessageContentOpened extends Update {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Message identifier.
		**/
		public long messageId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1520523131;

		/**
		 * The message content was opened. Updates voice note messages to &quot;listened&quot;, video note messages to &quot;viewed&quot; and starts the self-destruct timer.
		**/
		public UpdateMessageContentOpened() {}

		/**
		 * The message content was opened. Updates voice note messages to &quot;listened&quot;, video note messages to &quot;viewed&quot; and starts the self-destruct timer.
		 *
		 * @param chatId Chat identifier.
		 * @param messageId Message identifier.
		**/
		public UpdateMessageContentOpened(long chatId, long messageId) {
			this.chatId = chatId;
			this.messageId = messageId;
		}

		/**
		 * The message content was opened. Updates voice note messages to &quot;listened&quot;, video note messages to &quot;viewed&quot; and starts the self-destruct timer.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateMessageContentOpened(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateMessageContentOpened.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateMessageContentOpened.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateMessageContentOpened updateMessageContentOpened = (UpdateMessageContentOpened) o;
			if (this.chatId != updateMessageContentOpened.chatId) {
				return false;
			}
			if (this.messageId != updateMessageContentOpened.messageId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * A message with an unread mention was read.
	**/
	public static final class UpdateMessageMentionRead extends Update {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Message identifier.
		**/
		public long messageId;

		/**
		 * The new number of unread mention messages left in the chat.
		**/
		public int unreadMentionCount;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -252228282;

		/**
		 * A message with an unread mention was read.
		**/
		public UpdateMessageMentionRead() {}

		/**
		 * A message with an unread mention was read.
		 *
		 * @param chatId Chat identifier.
		 * @param messageId Message identifier.
		 * @param unreadMentionCount The new number of unread mention messages left in the chat.
		**/
		public UpdateMessageMentionRead(long chatId, long messageId, int unreadMentionCount) {
			this.chatId = chatId;
			this.messageId = messageId;
			this.unreadMentionCount = unreadMentionCount;
		}

		/**
		 * A message with an unread mention was read.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateMessageMentionRead(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
			this.unreadMentionCount = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateMessageMentionRead.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateMessageMentionRead.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
			output.writeInt(this.unreadMentionCount);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateMessageMentionRead updateMessageMentionRead = (UpdateMessageMentionRead) o;
			if (this.chatId != updateMessageMentionRead.chatId) {
				return false;
			}
			if (this.messageId != updateMessageMentionRead.messageId) {
				return false;
			}
			if (this.unreadMentionCount != updateMessageMentionRead.unreadMentionCount) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * The list of unread reactions added to a message was changed.
	**/
	public static final class UpdateMessageUnreadReactions extends Update {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Message identifier.
		**/
		public long messageId;

		/**
		 * The new list of unread reactions.
		**/
		public UnreadReaction[] unreadReactions;

		/**
		 * The new number of messages with unread reactions left in the chat.
		**/
		public int unreadReactionCount;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 942840008;

		/**
		 * The list of unread reactions added to a message was changed.
		**/
		public UpdateMessageUnreadReactions() {}

		/**
		 * The list of unread reactions added to a message was changed.
		 *
		 * @param chatId Chat identifier.
		 * @param messageId Message identifier.
		 * @param unreadReactions The new list of unread reactions.
		 * @param unreadReactionCount The new number of messages with unread reactions left in the chat.
		**/
		public UpdateMessageUnreadReactions(long chatId,
				long messageId,
				UnreadReaction[] unreadReactions,
				int unreadReactionCount) {
			this.chatId = chatId;
			this.messageId = messageId;
			this.unreadReactions = unreadReactions;
			this.unreadReactionCount = unreadReactionCount;
		}

		/**
		 * The list of unread reactions added to a message was changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateMessageUnreadReactions(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
			if (input.readBoolean()) {
				this.unreadReactions = new UnreadReaction[input.readInt()];
				for (int i = 0; i < this.unreadReactions.length; i++) {
					if (UnreadReaction.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.unreadReactions[i] = new UnreadReaction(input);
				}
			}
			this.unreadReactionCount = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateMessageUnreadReactions.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateMessageUnreadReactions.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
			if (this.unreadReactions == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.unreadReactions.length);
				for (int i = 0; i < this.unreadReactions.length; i++) {
					this.unreadReactions[i].serialize(output);
				}
			}
			output.writeInt(this.unreadReactionCount);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateMessageUnreadReactions updateMessageUnreadReactions = (UpdateMessageUnreadReactions) o;
			if (this.chatId != updateMessageUnreadReactions.chatId) {
				return false;
			}
			if (this.messageId != updateMessageUnreadReactions.messageId) {
				return false;
			}
			if (!Arrays.equals(this.unreadReactions, updateMessageUnreadReactions.unreadReactions)) {
				return false;
			}
			if (this.unreadReactionCount != updateMessageUnreadReactions.unreadReactionCount) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (Arrays.hashCode(this.unreadReactions));
			return result;
		}
	}

	/**
	 * A message with a live location was viewed. When the update is
	 * received, the application is supposed to update the live location.
	**/
	public static final class UpdateMessageLiveLocationViewed extends Update {


		/**
		 * Identifier of the chat with the live location message.
		**/
		public long chatId;

		/**
		 * Identifier of the message with live location.
		**/
		public long messageId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1308260971;

		/**
		 * A message with a live location was viewed. When the update is received, the application is supposed to update the live location.
		**/
		public UpdateMessageLiveLocationViewed() {}

		/**
		 * A message with a live location was viewed. When the update is received, the application is supposed to update the live location.
		 *
		 * @param chatId Identifier of the chat with the live location message.
		 * @param messageId Identifier of the message with live location.
		**/
		public UpdateMessageLiveLocationViewed(long chatId, long messageId) {
			this.chatId = chatId;
			this.messageId = messageId;
		}

		/**
		 * A message with a live location was viewed. When the update is received, the application is supposed to update the live location.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateMessageLiveLocationViewed(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateMessageLiveLocationViewed.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateMessageLiveLocationViewed.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateMessageLiveLocationViewed updateMessageLiveLocationViewed = (UpdateMessageLiveLocationViewed) o;
			if (this.chatId != updateMessageLiveLocationViewed.chatId) {
				return false;
			}
			if (this.messageId != updateMessageLiveLocationViewed.messageId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * A new chat has been loaded/created. This update is guaranteed to come
	 * before the chat identifier is returned to the application. The chat
	 * field changes will be reported through separate updates.
	**/
	public static final class UpdateNewChat extends Update {


		/**
		 * The chat.
		**/
		public Chat chat;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2075757773;

		/**
		 * A new chat has been loaded/created. This update is guaranteed to come before the chat identifier is returned to the application. The chat field changes will be reported through separate updates.
		**/
		public UpdateNewChat() {}

		/**
		 * A new chat has been loaded/created. This update is guaranteed to come before the chat identifier is returned to the application. The chat field changes will be reported through separate updates.
		 *
		 * @param chat The chat.
		**/
		public UpdateNewChat(Chat chat) {
			this.chat = chat;
		}

		/**
		 * A new chat has been loaded/created. This update is guaranteed to come before the chat identifier is returned to the application. The chat field changes will be reported through separate updates.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateNewChat(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Chat.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.chat = new Chat(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateNewChat.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateNewChat.CONSTRUCTOR);
			if (this.chat == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.chat.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateNewChat updateNewChat = (UpdateNewChat) o;
			if (!Objects.equals(this.chat, updateNewChat.chat)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.chat == null ? 0 : this.chat.hashCode();
		}
	}

	/**
	 * The title of a chat was changed.
	**/
	public static final class UpdateChatTitle extends Update {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * The new chat title.
		**/
		public String title;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -175405660;

		/**
		 * The title of a chat was changed.
		**/
		public UpdateChatTitle() {}

		/**
		 * The title of a chat was changed.
		 *
		 * @param chatId Chat identifier.
		 * @param title The new chat title.
		**/
		public UpdateChatTitle(long chatId, String title) {
			this.chatId = chatId;
			this.title = title;
		}

		/**
		 * The title of a chat was changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateChatTitle(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateChatTitle.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateChatTitle.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateChatTitle updateChatTitle = (UpdateChatTitle) o;
			if (this.chatId != updateChatTitle.chatId) {
				return false;
			}
			if (this.title != updateChatTitle.title) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.title == null ? 0 : this.title.hashCode());
			return result;
		}
	}

	/**
	 * A chat photo was changed.
	**/
	public static final class UpdateChatPhoto extends Update {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * The new chat photo; may be null.
		**/
		public ChatPhotoInfo photo;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -324713921;

		/**
		 * A chat photo was changed.
		**/
		public UpdateChatPhoto() {}

		/**
		 * A chat photo was changed.
		 *
		 * @param chatId Chat identifier.
		 * @param photo The new chat photo; may be null.
		**/
		public UpdateChatPhoto(long chatId, ChatPhotoInfo photo) {
			this.chatId = chatId;
			this.photo = photo;
		}

		/**
		 * A chat photo was changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateChatPhoto(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				if (ChatPhotoInfo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.photo = new ChatPhotoInfo(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateChatPhoto.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateChatPhoto.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.photo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.photo.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateChatPhoto updateChatPhoto = (UpdateChatPhoto) o;
			if (this.chatId != updateChatPhoto.chatId) {
				return false;
			}
			if (!Objects.equals(this.photo, updateChatPhoto.photo)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.photo == null ? 0 : this.photo.hashCode());
			return result;
		}
	}

	/**
	 * Chat permissions was changed.
	**/
	public static final class UpdateChatPermissions extends Update {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * The new chat permissions.
		**/
		public ChatPermissions permissions;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1622010003;

		/**
		 * Chat permissions was changed.
		**/
		public UpdateChatPermissions() {}

		/**
		 * Chat permissions was changed.
		 *
		 * @param chatId Chat identifier.
		 * @param permissions The new chat permissions.
		**/
		public UpdateChatPermissions(long chatId, ChatPermissions permissions) {
			this.chatId = chatId;
			this.permissions = permissions;
		}

		/**
		 * Chat permissions was changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateChatPermissions(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				if (ChatPermissions.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.permissions = new ChatPermissions(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateChatPermissions.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateChatPermissions.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.permissions == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.permissions.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateChatPermissions updateChatPermissions = (UpdateChatPermissions) o;
			if (this.chatId != updateChatPermissions.chatId) {
				return false;
			}
			if (!Objects.equals(this.permissions, updateChatPermissions.permissions)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.permissions == null ? 0 : this.permissions.hashCode());
			return result;
		}
	}

	/**
	 * The last message of a chat was changed. If lastMessage is null, then
	 * the last message in the chat became unknown. Some new unknown
	 * messages might be added to the chat in this case.
	**/
	public static final class UpdateChatLastMessage extends Update {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * The new last message in the chat; may be null.
		**/
		public Message lastMessage;

		/**
		 * The new chat positions in the chat lists.
		**/
		public ChatPosition[] positions;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -923244537;

		/**
		 * The last message of a chat was changed. If lastMessage is null, then the last message in the chat became unknown. Some new unknown messages might be added to the chat in this case.
		**/
		public UpdateChatLastMessage() {}

		/**
		 * The last message of a chat was changed. If lastMessage is null, then the last message in the chat became unknown. Some new unknown messages might be added to the chat in this case.
		 *
		 * @param chatId Chat identifier.
		 * @param lastMessage The new last message in the chat; may be null.
		 * @param positions The new chat positions in the chat lists.
		**/
		public UpdateChatLastMessage(long chatId, Message lastMessage, ChatPosition[] positions) {
			this.chatId = chatId;
			this.lastMessage = lastMessage;
			this.positions = positions;
		}

		/**
		 * The last message of a chat was changed. If lastMessage is null, then the last message in the chat became unknown. Some new unknown messages might be added to the chat in this case.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateChatLastMessage(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				if (Message.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.lastMessage = new Message(input);
			}
			if (input.readBoolean()) {
				this.positions = new ChatPosition[input.readInt()];
				for (int i = 0; i < this.positions.length; i++) {
					if (ChatPosition.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.positions[i] = new ChatPosition(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateChatLastMessage.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateChatLastMessage.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.lastMessage == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.lastMessage.serialize(output);
			}
			if (this.positions == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.positions.length);
				for (int i = 0; i < this.positions.length; i++) {
					this.positions[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateChatLastMessage updateChatLastMessage = (UpdateChatLastMessage) o;
			if (this.chatId != updateChatLastMessage.chatId) {
				return false;
			}
			if (!Objects.equals(this.lastMessage, updateChatLastMessage.lastMessage)) {
				return false;
			}
			if (!Arrays.equals(this.positions, updateChatLastMessage.positions)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.lastMessage == null ? 0 : this.lastMessage.hashCode());
			result = result * 31 + (Arrays.hashCode(this.positions));
			return result;
		}
	}

	/**
	 * The position of a chat in a chat list has changed. An
	 * updateChatLastMessage or updateChatDraftMessage update might be sent
	 * instead of the update.
	**/
	public static final class UpdateChatPosition extends Update {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * New chat position. If new order is 0, then the chat needs to be removed from the list.
		**/
		public ChatPosition position;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -8979849;

		/**
		 * The position of a chat in a chat list has changed. An updateChatLastMessage or updateChatDraftMessage update might be sent instead of the update.
		**/
		public UpdateChatPosition() {}

		/**
		 * The position of a chat in a chat list has changed. An updateChatLastMessage or updateChatDraftMessage update might be sent instead of the update.
		 *
		 * @param chatId Chat identifier.
		 * @param position New chat position. If new order is 0, then the chat needs to be removed from the list.
		**/
		public UpdateChatPosition(long chatId, ChatPosition position) {
			this.chatId = chatId;
			this.position = position;
		}

		/**
		 * The position of a chat in a chat list has changed. An updateChatLastMessage or updateChatDraftMessage update might be sent instead of the update.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateChatPosition(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				if (ChatPosition.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.position = new ChatPosition(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateChatPosition.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateChatPosition.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.position == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.position.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateChatPosition updateChatPosition = (UpdateChatPosition) o;
			if (this.chatId != updateChatPosition.chatId) {
				return false;
			}
			if (!Objects.equals(this.position, updateChatPosition.position)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.position == null ? 0 : this.position.hashCode());
			return result;
		}
	}

	/**
	 * Incoming messages were read or the number of unread messages has been
	 * changed.
	**/
	public static final class UpdateChatReadInbox extends Update {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Identifier of the last read incoming message.
		**/
		public long lastReadInboxMessageId;

		/**
		 * The number of unread messages left in the chat.
		**/
		public int unreadCount;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -797952281;

		/**
		 * Incoming messages were read or the number of unread messages has been changed.
		**/
		public UpdateChatReadInbox() {}

		/**
		 * Incoming messages were read or the number of unread messages has been changed.
		 *
		 * @param chatId Chat identifier.
		 * @param lastReadInboxMessageId Identifier of the last read incoming message.
		 * @param unreadCount The number of unread messages left in the chat.
		**/
		public UpdateChatReadInbox(long chatId, long lastReadInboxMessageId, int unreadCount) {
			this.chatId = chatId;
			this.lastReadInboxMessageId = lastReadInboxMessageId;
			this.unreadCount = unreadCount;
		}

		/**
		 * Incoming messages were read or the number of unread messages has been changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateChatReadInbox(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.lastReadInboxMessageId = input.readLong();
			this.unreadCount = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateChatReadInbox.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateChatReadInbox.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.lastReadInboxMessageId);
			output.writeInt(this.unreadCount);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateChatReadInbox updateChatReadInbox = (UpdateChatReadInbox) o;
			if (this.chatId != updateChatReadInbox.chatId) {
				return false;
			}
			if (this.lastReadInboxMessageId != updateChatReadInbox.lastReadInboxMessageId) {
				return false;
			}
			if (this.unreadCount != updateChatReadInbox.unreadCount) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Outgoing messages were read.
	**/
	public static final class UpdateChatReadOutbox extends Update {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Identifier of last read outgoing message.
		**/
		public long lastReadOutboxMessageId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 708334213;

		/**
		 * Outgoing messages were read.
		**/
		public UpdateChatReadOutbox() {}

		/**
		 * Outgoing messages were read.
		 *
		 * @param chatId Chat identifier.
		 * @param lastReadOutboxMessageId Identifier of last read outgoing message.
		**/
		public UpdateChatReadOutbox(long chatId, long lastReadOutboxMessageId) {
			this.chatId = chatId;
			this.lastReadOutboxMessageId = lastReadOutboxMessageId;
		}

		/**
		 * Outgoing messages were read.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateChatReadOutbox(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.lastReadOutboxMessageId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateChatReadOutbox.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateChatReadOutbox.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.lastReadOutboxMessageId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateChatReadOutbox updateChatReadOutbox = (UpdateChatReadOutbox) o;
			if (this.chatId != updateChatReadOutbox.chatId) {
				return false;
			}
			if (this.lastReadOutboxMessageId != updateChatReadOutbox.lastReadOutboxMessageId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * The chat action bar was changed.
	**/
	public static final class UpdateChatActionBar extends Update {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * The new value of the action bar; may be null.
		**/
		public ChatActionBar actionBar;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -643671870;

		/**
		 * The chat action bar was changed.
		**/
		public UpdateChatActionBar() {}

		/**
		 * The chat action bar was changed.
		 *
		 * @param chatId Chat identifier.
		 * @param actionBar The new value of the action bar; may be null.
		**/
		public UpdateChatActionBar(long chatId, ChatActionBar actionBar) {
			this.chatId = chatId;
			this.actionBar = actionBar;
		}

		/**
		 * The chat action bar was changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateChatActionBar(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ChatActionBarReportSpam.CONSTRUCTOR: this.actionBar = new ChatActionBarReportSpam(input); break;
					case ChatActionBarReportUnrelatedLocation.CONSTRUCTOR: this.actionBar = new ChatActionBarReportUnrelatedLocation(input); break;
					case ChatActionBarInviteMembers.CONSTRUCTOR: this.actionBar = new ChatActionBarInviteMembers(input); break;
					case ChatActionBarReportAddBlock.CONSTRUCTOR: this.actionBar = new ChatActionBarReportAddBlock(input); break;
					case ChatActionBarAddContact.CONSTRUCTOR: this.actionBar = new ChatActionBarAddContact(input); break;
					case ChatActionBarSharePhoneNumber.CONSTRUCTOR: this.actionBar = new ChatActionBarSharePhoneNumber(input); break;
					case ChatActionBarJoinRequest.CONSTRUCTOR: this.actionBar = new ChatActionBarJoinRequest(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateChatActionBar.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateChatActionBar.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.actionBar == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.actionBar.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateChatActionBar updateChatActionBar = (UpdateChatActionBar) o;
			if (this.chatId != updateChatActionBar.chatId) {
				return false;
			}
			if (!Objects.equals(this.actionBar, updateChatActionBar.actionBar)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.actionBar == null ? 0 : this.actionBar.hashCode());
			return result;
		}
	}

	/**
	 * The chat available reactions were changed.
	**/
	public static final class UpdateChatAvailableReactions extends Update {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * The new reactions, available in the chat.
		**/
		public ChatAvailableReactions availableReactions;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1967909895;

		/**
		 * The chat available reactions were changed.
		**/
		public UpdateChatAvailableReactions() {}

		/**
		 * The chat available reactions were changed.
		 *
		 * @param chatId Chat identifier.
		 * @param availableReactions The new reactions, available in the chat.
		**/
		public UpdateChatAvailableReactions(long chatId, ChatAvailableReactions availableReactions) {
			this.chatId = chatId;
			this.availableReactions = availableReactions;
		}

		/**
		 * The chat available reactions were changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateChatAvailableReactions(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ChatAvailableReactionsAll.CONSTRUCTOR: this.availableReactions = new ChatAvailableReactionsAll(input); break;
					case ChatAvailableReactionsSome.CONSTRUCTOR: this.availableReactions = new ChatAvailableReactionsSome(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateChatAvailableReactions.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateChatAvailableReactions.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.availableReactions == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.availableReactions.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateChatAvailableReactions updateChatAvailableReactions = (UpdateChatAvailableReactions) o;
			if (this.chatId != updateChatAvailableReactions.chatId) {
				return false;
			}
			if (!Objects.equals(this.availableReactions, updateChatAvailableReactions.availableReactions)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.availableReactions == null ? 0 : this.availableReactions.hashCode());
			return result;
		}
	}

	/**
	 * A chat draft has changed. Be aware that the update may come in the
	 * currently opened chat but with old content of the draft. If the user
	 * has changed the content of the draft, this update mustn&#039;t be
	 * applied.
	**/
	public static final class UpdateChatDraftMessage extends Update {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * The new draft message; may be null.
		**/
		public DraftMessage draftMessage;

		/**
		 * The new chat positions in the chat lists.
		**/
		public ChatPosition[] positions;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1455190380;

		/**
		 * A chat draft has changed. Be aware that the update may come in the currently opened chat but with old content of the draft. If the user has changed the content of the draft, this update mustn&#039;t be applied.
		**/
		public UpdateChatDraftMessage() {}

		/**
		 * A chat draft has changed. Be aware that the update may come in the currently opened chat but with old content of the draft. If the user has changed the content of the draft, this update mustn&#039;t be applied.
		 *
		 * @param chatId Chat identifier.
		 * @param draftMessage The new draft message; may be null.
		 * @param positions The new chat positions in the chat lists.
		**/
		public UpdateChatDraftMessage(long chatId,
				DraftMessage draftMessage,
				ChatPosition[] positions) {
			this.chatId = chatId;
			this.draftMessage = draftMessage;
			this.positions = positions;
		}

		/**
		 * A chat draft has changed. Be aware that the update may come in the currently opened chat but with old content of the draft. If the user has changed the content of the draft, this update mustn&#039;t be applied.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateChatDraftMessage(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				if (DraftMessage.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.draftMessage = new DraftMessage(input);
			}
			if (input.readBoolean()) {
				this.positions = new ChatPosition[input.readInt()];
				for (int i = 0; i < this.positions.length; i++) {
					if (ChatPosition.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.positions[i] = new ChatPosition(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateChatDraftMessage.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateChatDraftMessage.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.draftMessage == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.draftMessage.serialize(output);
			}
			if (this.positions == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.positions.length);
				for (int i = 0; i < this.positions.length; i++) {
					this.positions[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateChatDraftMessage updateChatDraftMessage = (UpdateChatDraftMessage) o;
			if (this.chatId != updateChatDraftMessage.chatId) {
				return false;
			}
			if (!Objects.equals(this.draftMessage, updateChatDraftMessage.draftMessage)) {
				return false;
			}
			if (!Arrays.equals(this.positions, updateChatDraftMessage.positions)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.draftMessage == null ? 0 : this.draftMessage.hashCode());
			result = result * 31 + (Arrays.hashCode(this.positions));
			return result;
		}
	}

	/**
	 * The message sender that is selected to send messages in a chat has
	 * changed.
	**/
	public static final class UpdateChatMessageSender extends Update {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * New value of messageSenderId; may be null if the user can&#039;t change message sender.
		**/
		public MessageSender messageSenderId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2003849793;

		/**
		 * The message sender that is selected to send messages in a chat has changed.
		**/
		public UpdateChatMessageSender() {}

		/**
		 * The message sender that is selected to send messages in a chat has changed.
		 *
		 * @param chatId Chat identifier.
		 * @param messageSenderId New value of messageSenderId; may be null if the user can&#039;t change message sender.
		**/
		public UpdateChatMessageSender(long chatId, MessageSender messageSenderId) {
			this.chatId = chatId;
			this.messageSenderId = messageSenderId;
		}

		/**
		 * The message sender that is selected to send messages in a chat has changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateChatMessageSender(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case MessageSenderUser.CONSTRUCTOR: this.messageSenderId = new MessageSenderUser(input); break;
					case MessageSenderChat.CONSTRUCTOR: this.messageSenderId = new MessageSenderChat(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateChatMessageSender.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateChatMessageSender.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.messageSenderId == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.messageSenderId.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateChatMessageSender updateChatMessageSender = (UpdateChatMessageSender) o;
			if (this.chatId != updateChatMessageSender.chatId) {
				return false;
			}
			if (!Objects.equals(this.messageSenderId, updateChatMessageSender.messageSenderId)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.messageSenderId == null ? 0 : this.messageSenderId.hashCode());
			return result;
		}
	}

	/**
	 * The message auto-delete or self-destruct timer setting for a chat was
	 * changed.
	**/
	public static final class UpdateChatMessageAutoDeleteTime extends Update {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * New value of messageAutoDeleteTime.
		**/
		public int messageAutoDeleteTime;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1900174821;

		/**
		 * The message auto-delete or self-destruct timer setting for a chat was changed.
		**/
		public UpdateChatMessageAutoDeleteTime() {}

		/**
		 * The message auto-delete or self-destruct timer setting for a chat was changed.
		 *
		 * @param chatId Chat identifier.
		 * @param messageAutoDeleteTime New value of messageAutoDeleteTime.
		**/
		public UpdateChatMessageAutoDeleteTime(long chatId, int messageAutoDeleteTime) {
			this.chatId = chatId;
			this.messageAutoDeleteTime = messageAutoDeleteTime;
		}

		/**
		 * The message auto-delete or self-destruct timer setting for a chat was changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateChatMessageAutoDeleteTime(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageAutoDeleteTime = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateChatMessageAutoDeleteTime.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateChatMessageAutoDeleteTime.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeInt(this.messageAutoDeleteTime);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateChatMessageAutoDeleteTime updateChatMessageAutoDeleteTime = (UpdateChatMessageAutoDeleteTime) o;
			if (this.chatId != updateChatMessageAutoDeleteTime.chatId) {
				return false;
			}
			if (this.messageAutoDeleteTime != updateChatMessageAutoDeleteTime.messageAutoDeleteTime) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Notification settings for a chat were changed.
	**/
	public static final class UpdateChatNotificationSettings extends Update {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * The new notification settings.
		**/
		public ChatNotificationSettings notificationSettings;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -803163050;

		/**
		 * Notification settings for a chat were changed.
		**/
		public UpdateChatNotificationSettings() {}

		/**
		 * Notification settings for a chat were changed.
		 *
		 * @param chatId Chat identifier.
		 * @param notificationSettings The new notification settings.
		**/
		public UpdateChatNotificationSettings(long chatId, ChatNotificationSettings notificationSettings) {
			this.chatId = chatId;
			this.notificationSettings = notificationSettings;
		}

		/**
		 * Notification settings for a chat were changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateChatNotificationSettings(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				if (ChatNotificationSettings.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.notificationSettings = new ChatNotificationSettings(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateChatNotificationSettings.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateChatNotificationSettings.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.notificationSettings == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.notificationSettings.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateChatNotificationSettings updateChatNotificationSettings = (UpdateChatNotificationSettings) o;
			if (this.chatId != updateChatNotificationSettings.chatId) {
				return false;
			}
			if (!Objects.equals(this.notificationSettings, updateChatNotificationSettings.notificationSettings)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.notificationSettings == null ? 0 : this.notificationSettings.hashCode());
			return result;
		}
	}

	/**
	 * The chat pending join requests were changed.
	**/
	public static final class UpdateChatPendingJoinRequests extends Update {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * The new data about pending join requests; may be null.
		**/
		public ChatJoinRequestsInfo pendingJoinRequests;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 348578785;

		/**
		 * The chat pending join requests were changed.
		**/
		public UpdateChatPendingJoinRequests() {}

		/**
		 * The chat pending join requests were changed.
		 *
		 * @param chatId Chat identifier.
		 * @param pendingJoinRequests The new data about pending join requests; may be null.
		**/
		public UpdateChatPendingJoinRequests(long chatId, ChatJoinRequestsInfo pendingJoinRequests) {
			this.chatId = chatId;
			this.pendingJoinRequests = pendingJoinRequests;
		}

		/**
		 * The chat pending join requests were changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateChatPendingJoinRequests(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				if (ChatJoinRequestsInfo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.pendingJoinRequests = new ChatJoinRequestsInfo(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateChatPendingJoinRequests.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateChatPendingJoinRequests.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.pendingJoinRequests == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.pendingJoinRequests.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateChatPendingJoinRequests updateChatPendingJoinRequests = (UpdateChatPendingJoinRequests) o;
			if (this.chatId != updateChatPendingJoinRequests.chatId) {
				return false;
			}
			if (!Objects.equals(this.pendingJoinRequests, updateChatPendingJoinRequests.pendingJoinRequests)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.pendingJoinRequests == null ? 0 : this.pendingJoinRequests.hashCode());
			return result;
		}
	}

	/**
	 * The default chat reply markup was changed. Can occur because new
	 * messages with reply markup were received or because an old reply
	 * markup was hidden by the user.
	**/
	public static final class UpdateChatReplyMarkup extends Update {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Identifier of the message from which reply markup needs to be used; 0 if there is no default custom reply markup in the chat.
		**/
		public long replyMarkupMessageId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1309386144;

		/**
		 * The default chat reply markup was changed. Can occur because new messages with reply markup were received or because an old reply markup was hidden by the user.
		**/
		public UpdateChatReplyMarkup() {}

		/**
		 * The default chat reply markup was changed. Can occur because new messages with reply markup were received or because an old reply markup was hidden by the user.
		 *
		 * @param chatId Chat identifier.
		 * @param replyMarkupMessageId Identifier of the message from which reply markup needs to be used; 0 if there is no default custom reply markup in the chat.
		**/
		public UpdateChatReplyMarkup(long chatId, long replyMarkupMessageId) {
			this.chatId = chatId;
			this.replyMarkupMessageId = replyMarkupMessageId;
		}

		/**
		 * The default chat reply markup was changed. Can occur because new messages with reply markup were received or because an old reply markup was hidden by the user.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateChatReplyMarkup(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.replyMarkupMessageId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateChatReplyMarkup.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateChatReplyMarkup.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.replyMarkupMessageId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateChatReplyMarkup updateChatReplyMarkup = (UpdateChatReplyMarkup) o;
			if (this.chatId != updateChatReplyMarkup.chatId) {
				return false;
			}
			if (this.replyMarkupMessageId != updateChatReplyMarkup.replyMarkupMessageId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * The chat background was changed.
	**/
	public static final class UpdateChatBackground extends Update {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * The new chat background; may be null if background was reset to default.
		**/
		public ChatBackground background;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -6473549;

		/**
		 * The chat background was changed.
		**/
		public UpdateChatBackground() {}

		/**
		 * The chat background was changed.
		 *
		 * @param chatId Chat identifier.
		 * @param background The new chat background; may be null if background was reset to default.
		**/
		public UpdateChatBackground(long chatId, ChatBackground background) {
			this.chatId = chatId;
			this.background = background;
		}

		/**
		 * The chat background was changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateChatBackground(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				if (ChatBackground.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.background = new ChatBackground(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateChatBackground.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateChatBackground.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.background == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.background.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateChatBackground updateChatBackground = (UpdateChatBackground) o;
			if (this.chatId != updateChatBackground.chatId) {
				return false;
			}
			if (!Objects.equals(this.background, updateChatBackground.background)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.background == null ? 0 : this.background.hashCode());
			return result;
		}
	}

	/**
	 * The chat theme was changed.
	**/
	public static final class UpdateChatTheme extends Update {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * The new name of the chat theme; may be empty if theme was reset to default.
		**/
		public String themeName;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 838063205;

		/**
		 * The chat theme was changed.
		**/
		public UpdateChatTheme() {}

		/**
		 * The chat theme was changed.
		 *
		 * @param chatId Chat identifier.
		 * @param themeName The new name of the chat theme; may be empty if theme was reset to default.
		**/
		public UpdateChatTheme(long chatId, String themeName) {
			this.chatId = chatId;
			this.themeName = themeName;
		}

		/**
		 * The chat theme was changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateChatTheme(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				byte[] themeNameTmp = new byte[input.readInt()];
				input.readFully(themeNameTmp);
				this.themeName = new String(themeNameTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateChatTheme.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateChatTheme.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.themeName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] themeNameTmp = this.themeName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(themeNameTmp.length);
				output.write(themeNameTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateChatTheme updateChatTheme = (UpdateChatTheme) o;
			if (this.chatId != updateChatTheme.chatId) {
				return false;
			}
			if (this.themeName != updateChatTheme.themeName) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.themeName == null ? 0 : this.themeName.hashCode());
			return result;
		}
	}

	/**
	 * The chat unreadMentionCount has changed.
	**/
	public static final class UpdateChatUnreadMentionCount extends Update {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * The number of unread mention messages left in the chat.
		**/
		public int unreadMentionCount;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2131461348;

		/**
		 * The chat unreadMentionCount has changed.
		**/
		public UpdateChatUnreadMentionCount() {}

		/**
		 * The chat unreadMentionCount has changed.
		 *
		 * @param chatId Chat identifier.
		 * @param unreadMentionCount The number of unread mention messages left in the chat.
		**/
		public UpdateChatUnreadMentionCount(long chatId, int unreadMentionCount) {
			this.chatId = chatId;
			this.unreadMentionCount = unreadMentionCount;
		}

		/**
		 * The chat unreadMentionCount has changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateChatUnreadMentionCount(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.unreadMentionCount = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateChatUnreadMentionCount.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateChatUnreadMentionCount.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeInt(this.unreadMentionCount);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateChatUnreadMentionCount updateChatUnreadMentionCount = (UpdateChatUnreadMentionCount) o;
			if (this.chatId != updateChatUnreadMentionCount.chatId) {
				return false;
			}
			if (this.unreadMentionCount != updateChatUnreadMentionCount.unreadMentionCount) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * The chat unreadReactionCount has changed.
	**/
	public static final class UpdateChatUnreadReactionCount extends Update {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * The number of messages with unread reactions left in the chat.
		**/
		public int unreadReactionCount;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2124399395;

		/**
		 * The chat unreadReactionCount has changed.
		**/
		public UpdateChatUnreadReactionCount() {}

		/**
		 * The chat unreadReactionCount has changed.
		 *
		 * @param chatId Chat identifier.
		 * @param unreadReactionCount The number of messages with unread reactions left in the chat.
		**/
		public UpdateChatUnreadReactionCount(long chatId, int unreadReactionCount) {
			this.chatId = chatId;
			this.unreadReactionCount = unreadReactionCount;
		}

		/**
		 * The chat unreadReactionCount has changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateChatUnreadReactionCount(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.unreadReactionCount = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateChatUnreadReactionCount.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateChatUnreadReactionCount.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeInt(this.unreadReactionCount);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateChatUnreadReactionCount updateChatUnreadReactionCount = (UpdateChatUnreadReactionCount) o;
			if (this.chatId != updateChatUnreadReactionCount.chatId) {
				return false;
			}
			if (this.unreadReactionCount != updateChatUnreadReactionCount.unreadReactionCount) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * A chat video chat state has changed.
	**/
	public static final class UpdateChatVideoChat extends Update {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * New value of videoChat.
		**/
		public VideoChat videoChat;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 637226150;

		/**
		 * A chat video chat state has changed.
		**/
		public UpdateChatVideoChat() {}

		/**
		 * A chat video chat state has changed.
		 *
		 * @param chatId Chat identifier.
		 * @param videoChat New value of videoChat.
		**/
		public UpdateChatVideoChat(long chatId, VideoChat videoChat) {
			this.chatId = chatId;
			this.videoChat = videoChat;
		}

		/**
		 * A chat video chat state has changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateChatVideoChat(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				if (VideoChat.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.videoChat = new VideoChat(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateChatVideoChat.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateChatVideoChat.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.videoChat == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.videoChat.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateChatVideoChat updateChatVideoChat = (UpdateChatVideoChat) o;
			if (this.chatId != updateChatVideoChat.chatId) {
				return false;
			}
			if (!Objects.equals(this.videoChat, updateChatVideoChat.videoChat)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.videoChat == null ? 0 : this.videoChat.hashCode());
			return result;
		}
	}

	/**
	 * The value of the default disableNotification parameter, used when a
	 * message is sent to the chat, was changed.
	**/
	public static final class UpdateChatDefaultDisableNotification extends Update {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * The new defaultDisableNotification value.
		**/
		public boolean defaultDisableNotification;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 464087707;

		/**
		 * The value of the default disableNotification parameter, used when a message is sent to the chat, was changed.
		**/
		public UpdateChatDefaultDisableNotification() {}

		/**
		 * The value of the default disableNotification parameter, used when a message is sent to the chat, was changed.
		 *
		 * @param chatId Chat identifier.
		 * @param defaultDisableNotification The new defaultDisableNotification value.
		**/
		public UpdateChatDefaultDisableNotification(long chatId, boolean defaultDisableNotification) {
			this.chatId = chatId;
			this.defaultDisableNotification = defaultDisableNotification;
		}

		/**
		 * The value of the default disableNotification parameter, used when a message is sent to the chat, was changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateChatDefaultDisableNotification(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.defaultDisableNotification = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateChatDefaultDisableNotification.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateChatDefaultDisableNotification.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeBoolean(this.defaultDisableNotification);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateChatDefaultDisableNotification updateChatDefaultDisableNotification = (UpdateChatDefaultDisableNotification) o;
			if (this.chatId != updateChatDefaultDisableNotification.chatId) {
				return false;
			}
			if (this.defaultDisableNotification != updateChatDefaultDisableNotification.defaultDisableNotification) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * A chat content was allowed or restricted for saving.
	**/
	public static final class UpdateChatHasProtectedContent extends Update {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * New value of hasProtectedContent.
		**/
		public boolean hasProtectedContent;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1800406811;

		/**
		 * A chat content was allowed or restricted for saving.
		**/
		public UpdateChatHasProtectedContent() {}

		/**
		 * A chat content was allowed or restricted for saving.
		 *
		 * @param chatId Chat identifier.
		 * @param hasProtectedContent New value of hasProtectedContent.
		**/
		public UpdateChatHasProtectedContent(long chatId, boolean hasProtectedContent) {
			this.chatId = chatId;
			this.hasProtectedContent = hasProtectedContent;
		}

		/**
		 * A chat content was allowed or restricted for saving.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateChatHasProtectedContent(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.hasProtectedContent = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateChatHasProtectedContent.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateChatHasProtectedContent.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeBoolean(this.hasProtectedContent);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateChatHasProtectedContent updateChatHasProtectedContent = (UpdateChatHasProtectedContent) o;
			if (this.chatId != updateChatHasProtectedContent.chatId) {
				return false;
			}
			if (this.hasProtectedContent != updateChatHasProtectedContent.hasProtectedContent) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Translation of chat messages was enabled or disabled.
	**/
	public static final class UpdateChatIsTranslatable extends Update {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * New value of isTranslatable.
		**/
		public boolean isTranslatable;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2063799831;

		/**
		 * Translation of chat messages was enabled or disabled.
		**/
		public UpdateChatIsTranslatable() {}

		/**
		 * Translation of chat messages was enabled or disabled.
		 *
		 * @param chatId Chat identifier.
		 * @param isTranslatable New value of isTranslatable.
		**/
		public UpdateChatIsTranslatable(long chatId, boolean isTranslatable) {
			this.chatId = chatId;
			this.isTranslatable = isTranslatable;
		}

		/**
		 * Translation of chat messages was enabled or disabled.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateChatIsTranslatable(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.isTranslatable = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateChatIsTranslatable.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateChatIsTranslatable.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeBoolean(this.isTranslatable);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateChatIsTranslatable updateChatIsTranslatable = (UpdateChatIsTranslatable) o;
			if (this.chatId != updateChatIsTranslatable.chatId) {
				return false;
			}
			if (this.isTranslatable != updateChatIsTranslatable.isTranslatable) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * A chat was marked as unread or was read.
	**/
	public static final class UpdateChatIsMarkedAsUnread extends Update {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * New value of isMarkedAsUnread.
		**/
		public boolean isMarkedAsUnread;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1468347188;

		/**
		 * A chat was marked as unread or was read.
		**/
		public UpdateChatIsMarkedAsUnread() {}

		/**
		 * A chat was marked as unread or was read.
		 *
		 * @param chatId Chat identifier.
		 * @param isMarkedAsUnread New value of isMarkedAsUnread.
		**/
		public UpdateChatIsMarkedAsUnread(long chatId, boolean isMarkedAsUnread) {
			this.chatId = chatId;
			this.isMarkedAsUnread = isMarkedAsUnread;
		}

		/**
		 * A chat was marked as unread or was read.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateChatIsMarkedAsUnread(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.isMarkedAsUnread = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateChatIsMarkedAsUnread.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateChatIsMarkedAsUnread.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeBoolean(this.isMarkedAsUnread);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateChatIsMarkedAsUnread updateChatIsMarkedAsUnread = (UpdateChatIsMarkedAsUnread) o;
			if (this.chatId != updateChatIsMarkedAsUnread.chatId) {
				return false;
			}
			if (this.isMarkedAsUnread != updateChatIsMarkedAsUnread.isMarkedAsUnread) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * A chat was blocked or unblocked.
	**/
	public static final class UpdateChatIsBlocked extends Update {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * New value of isBlocked.
		**/
		public boolean isBlocked;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1998946752;

		/**
		 * A chat was blocked or unblocked.
		**/
		public UpdateChatIsBlocked() {}

		/**
		 * A chat was blocked or unblocked.
		 *
		 * @param chatId Chat identifier.
		 * @param isBlocked New value of isBlocked.
		**/
		public UpdateChatIsBlocked(long chatId, boolean isBlocked) {
			this.chatId = chatId;
			this.isBlocked = isBlocked;
		}

		/**
		 * A chat was blocked or unblocked.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateChatIsBlocked(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.isBlocked = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateChatIsBlocked.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateChatIsBlocked.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeBoolean(this.isBlocked);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateChatIsBlocked updateChatIsBlocked = (UpdateChatIsBlocked) o;
			if (this.chatId != updateChatIsBlocked.chatId) {
				return false;
			}
			if (this.isBlocked != updateChatIsBlocked.isBlocked) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * A chat&#039;s hasScheduledMessages field has changed.
	**/
	public static final class UpdateChatHasScheduledMessages extends Update {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * New value of hasScheduledMessages.
		**/
		public boolean hasScheduledMessages;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2064958167;

		/**
		 * A chat&#039;s hasScheduledMessages field has changed.
		**/
		public UpdateChatHasScheduledMessages() {}

		/**
		 * A chat&#039;s hasScheduledMessages field has changed.
		 *
		 * @param chatId Chat identifier.
		 * @param hasScheduledMessages New value of hasScheduledMessages.
		**/
		public UpdateChatHasScheduledMessages(long chatId, boolean hasScheduledMessages) {
			this.chatId = chatId;
			this.hasScheduledMessages = hasScheduledMessages;
		}

		/**
		 * A chat&#039;s hasScheduledMessages field has changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateChatHasScheduledMessages(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.hasScheduledMessages = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateChatHasScheduledMessages.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateChatHasScheduledMessages.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeBoolean(this.hasScheduledMessages);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateChatHasScheduledMessages updateChatHasScheduledMessages = (UpdateChatHasScheduledMessages) o;
			if (this.chatId != updateChatHasScheduledMessages.chatId) {
				return false;
			}
			if (this.hasScheduledMessages != updateChatHasScheduledMessages.hasScheduledMessages) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * The list of chat folders or a chat folder has changed.
	**/
	public static final class UpdateChatFolders extends Update {


		/**
		 * The new list of chat folders.
		**/
		public ChatFolderInfo[] chatFolders;

		/**
		 * Position of the main chat list among chat folders, 0-based.
		**/
		public int mainChatListPosition;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1892046525;

		/**
		 * The list of chat folders or a chat folder has changed.
		**/
		public UpdateChatFolders() {}

		/**
		 * The list of chat folders or a chat folder has changed.
		 *
		 * @param chatFolders The new list of chat folders.
		 * @param mainChatListPosition Position of the main chat list among chat folders, 0-based.
		**/
		public UpdateChatFolders(ChatFolderInfo[] chatFolders, int mainChatListPosition) {
			this.chatFolders = chatFolders;
			this.mainChatListPosition = mainChatListPosition;
		}

		/**
		 * The list of chat folders or a chat folder has changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateChatFolders(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.chatFolders = new ChatFolderInfo[input.readInt()];
				for (int i = 0; i < this.chatFolders.length; i++) {
					if (ChatFolderInfo.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.chatFolders[i] = new ChatFolderInfo(input);
				}
			}
			this.mainChatListPosition = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateChatFolders.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateChatFolders.CONSTRUCTOR);
			if (this.chatFolders == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.chatFolders.length);
				for (int i = 0; i < this.chatFolders.length; i++) {
					this.chatFolders[i].serialize(output);
				}
			}
			output.writeInt(this.mainChatListPosition);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateChatFolders updateChatFolders = (UpdateChatFolders) o;
			if (!Arrays.equals(this.chatFolders, updateChatFolders.chatFolders)) {
				return false;
			}
			if (this.mainChatListPosition != updateChatFolders.mainChatListPosition) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.mainChatListPosition);
			result = result * 31 + (Arrays.hashCode(this.chatFolders));
			return result;
		}
	}

	/**
	 * The number of online group members has changed. This update with
	 * non-zero number of online group members is sent only for currently
	 * opened chats. There is no guarantee that it will be sent just after
	 * the number of online users has changed.
	**/
	public static final class UpdateChatOnlineMemberCount extends Update {


		/**
		 * Identifier of the chat.
		**/
		public long chatId;

		/**
		 * New number of online members in the chat, or 0 if unknown.
		**/
		public int onlineMemberCount;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 487369373;

		/**
		 * The number of online group members has changed. This update with non-zero number of online group members is sent only for currently opened chats. There is no guarantee that it will be sent just after the number of online users has changed.
		**/
		public UpdateChatOnlineMemberCount() {}

		/**
		 * The number of online group members has changed. This update with non-zero number of online group members is sent only for currently opened chats. There is no guarantee that it will be sent just after the number of online users has changed.
		 *
		 * @param chatId Identifier of the chat.
		 * @param onlineMemberCount New number of online members in the chat, or 0 if unknown.
		**/
		public UpdateChatOnlineMemberCount(long chatId, int onlineMemberCount) {
			this.chatId = chatId;
			this.onlineMemberCount = onlineMemberCount;
		}

		/**
		 * The number of online group members has changed. This update with non-zero number of online group members is sent only for currently opened chats. There is no guarantee that it will be sent just after the number of online users has changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateChatOnlineMemberCount(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.onlineMemberCount = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateChatOnlineMemberCount.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateChatOnlineMemberCount.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeInt(this.onlineMemberCount);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateChatOnlineMemberCount updateChatOnlineMemberCount = (UpdateChatOnlineMemberCount) o;
			if (this.chatId != updateChatOnlineMemberCount.chatId) {
				return false;
			}
			if (this.onlineMemberCount != updateChatOnlineMemberCount.onlineMemberCount) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Basic information about a topic in a forum chat was changed.
	**/
	public static final class UpdateForumTopicInfo extends Update {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * New information about the topic.
		**/
		public ForumTopicInfo info;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1802448073;

		/**
		 * Basic information about a topic in a forum chat was changed.
		**/
		public UpdateForumTopicInfo() {}

		/**
		 * Basic information about a topic in a forum chat was changed.
		 *
		 * @param chatId Chat identifier.
		 * @param info New information about the topic.
		**/
		public UpdateForumTopicInfo(long chatId, ForumTopicInfo info) {
			this.chatId = chatId;
			this.info = info;
		}

		/**
		 * Basic information about a topic in a forum chat was changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateForumTopicInfo(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				if (ForumTopicInfo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.info = new ForumTopicInfo(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateForumTopicInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateForumTopicInfo.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.info == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.info.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateForumTopicInfo updateForumTopicInfo = (UpdateForumTopicInfo) o;
			if (this.chatId != updateForumTopicInfo.chatId) {
				return false;
			}
			if (!Objects.equals(this.info, updateForumTopicInfo.info)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.info == null ? 0 : this.info.hashCode());
			return result;
		}
	}

	/**
	 * Notification settings for some type of chats were updated.
	**/
	public static final class UpdateScopeNotificationSettings extends Update {


		/**
		 * Types of chats for which notification settings were updated.
		**/
		public NotificationSettingsScope scope;

		/**
		 * The new notification settings.
		**/
		public ScopeNotificationSettings notificationSettings;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1203975309;

		/**
		 * Notification settings for some type of chats were updated.
		**/
		public UpdateScopeNotificationSettings() {}

		/**
		 * Notification settings for some type of chats were updated.
		 *
		 * @param scope Types of chats for which notification settings were updated.
		 * @param notificationSettings The new notification settings.
		**/
		public UpdateScopeNotificationSettings(NotificationSettingsScope scope,
				ScopeNotificationSettings notificationSettings) {
			this.scope = scope;
			this.notificationSettings = notificationSettings;
		}

		/**
		 * Notification settings for some type of chats were updated.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateScopeNotificationSettings(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case NotificationSettingsScopePrivateChats.CONSTRUCTOR: this.scope = new NotificationSettingsScopePrivateChats(input); break;
					case NotificationSettingsScopeGroupChats.CONSTRUCTOR: this.scope = new NotificationSettingsScopeGroupChats(input); break;
					case NotificationSettingsScopeChannelChats.CONSTRUCTOR: this.scope = new NotificationSettingsScopeChannelChats(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				if (ScopeNotificationSettings.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.notificationSettings = new ScopeNotificationSettings(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateScopeNotificationSettings.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateScopeNotificationSettings.CONSTRUCTOR);
			if (this.scope == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.scope.serialize(output);
			}
			if (this.notificationSettings == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.notificationSettings.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateScopeNotificationSettings updateScopeNotificationSettings = (UpdateScopeNotificationSettings) o;
			if (!Objects.equals(this.scope, updateScopeNotificationSettings.scope)) {
				return false;
			}
			if (!Objects.equals(this.notificationSettings, updateScopeNotificationSettings.notificationSettings)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.scope == null ? 0 : this.scope.hashCode();
			result = result * 31 + (this.notificationSettings == null ? 0 : this.notificationSettings.hashCode());
			return result;
		}
	}

	/**
	 * A notification was changed.
	**/
	public static final class UpdateNotification extends Update {


		/**
		 * Unique notification group identifier.
		**/
		public int notificationGroupId;

		/**
		 * Changed notification.
		**/
		public Notification notification;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1897496876;

		/**
		 * A notification was changed.
		**/
		public UpdateNotification() {}

		/**
		 * A notification was changed.
		 *
		 * @param notificationGroupId Unique notification group identifier.
		 * @param notification Changed notification.
		**/
		public UpdateNotification(int notificationGroupId, Notification notification) {
			this.notificationGroupId = notificationGroupId;
			this.notification = notification;
		}

		/**
		 * A notification was changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateNotification(DataInput input) throws IOException {
			this.notificationGroupId = input.readInt();
			if (input.readBoolean()) {
				if (Notification.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.notification = new Notification(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateNotification.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateNotification.CONSTRUCTOR);
			output.writeInt(this.notificationGroupId);
			if (this.notification == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.notification.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateNotification updateNotification = (UpdateNotification) o;
			if (this.notificationGroupId != updateNotification.notificationGroupId) {
				return false;
			}
			if (!Objects.equals(this.notification, updateNotification.notification)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.notificationGroupId);
			result = result * 31 + (this.notification == null ? 0 : this.notification.hashCode());
			return result;
		}
	}

	/**
	 * A list of active notifications in a notification group has changed.
	**/
	public static final class UpdateNotificationGroup extends Update {


		/**
		 * Unique notification group identifier.
		**/
		public int notificationGroupId;

		/**
		 * New type of the notification group.
		**/
		public NotificationGroupType type;

		/**
		 * Identifier of a chat to which all notifications in the group belong.
		**/
		public long chatId;

		/**
		 * Chat identifier, which notification settings must be applied to the added notifications.
		**/
		public long notificationSettingsChatId;

		/**
		 * Identifier of the notification sound to be played; 0 if sound is disabled.
		**/
		public long notificationSoundId;

		/**
		 * Total number of unread notifications in the group, can be bigger than number of active notifications.
		**/
		public int totalCount;

		/**
		 * List of added group notifications, sorted by notification ID.
		**/
		public Notification[] addedNotifications;

		/**
		 * Identifiers of removed group notifications, sorted by notification ID.
		**/
		public int[] removedNotificationIds;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1381081378;

		/**
		 * A list of active notifications in a notification group has changed.
		**/
		public UpdateNotificationGroup() {}

		/**
		 * A list of active notifications in a notification group has changed.
		 *
		 * @param notificationGroupId Unique notification group identifier.
		 * @param type New type of the notification group.
		 * @param chatId Identifier of a chat to which all notifications in the group belong.
		 * @param notificationSettingsChatId Chat identifier, which notification settings must be applied to the added notifications.
		 * @param notificationSoundId Identifier of the notification sound to be played; 0 if sound is disabled.
		 * @param totalCount Total number of unread notifications in the group, can be bigger than number of active notifications.
		 * @param addedNotifications List of added group notifications, sorted by notification ID.
		 * @param removedNotificationIds Identifiers of removed group notifications, sorted by notification ID.
		**/
		public UpdateNotificationGroup(int notificationGroupId,
				NotificationGroupType type,
				long chatId,
				long notificationSettingsChatId,
				long notificationSoundId,
				int totalCount,
				Notification[] addedNotifications,
				int[] removedNotificationIds) {
			this.notificationGroupId = notificationGroupId;
			this.type = type;
			this.chatId = chatId;
			this.notificationSettingsChatId = notificationSettingsChatId;
			this.notificationSoundId = notificationSoundId;
			this.totalCount = totalCount;
			this.addedNotifications = addedNotifications;
			this.removedNotificationIds = removedNotificationIds;
		}

		/**
		 * A list of active notifications in a notification group has changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateNotificationGroup(DataInput input) throws IOException {
			this.notificationGroupId = input.readInt();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case NotificationGroupTypeMessages.CONSTRUCTOR: this.type = new NotificationGroupTypeMessages(input); break;
					case NotificationGroupTypeMentions.CONSTRUCTOR: this.type = new NotificationGroupTypeMentions(input); break;
					case NotificationGroupTypeSecretChat.CONSTRUCTOR: this.type = new NotificationGroupTypeSecretChat(input); break;
					case NotificationGroupTypeCalls.CONSTRUCTOR: this.type = new NotificationGroupTypeCalls(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.chatId = input.readLong();
			this.notificationSettingsChatId = input.readLong();
			this.notificationSoundId = input.readLong();
			this.totalCount = input.readInt();
			if (input.readBoolean()) {
				this.addedNotifications = new Notification[input.readInt()];
				for (int i = 0; i < this.addedNotifications.length; i++) {
					if (Notification.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.addedNotifications[i] = new Notification(input);
				}
			}
			if (input.readBoolean()) {
				this.removedNotificationIds = new int[input.readInt()];
				for (int i = 0; i < this.removedNotificationIds.length; i++) {
					this.removedNotificationIds[i] = input.readInt();
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateNotificationGroup.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateNotificationGroup.CONSTRUCTOR);
			output.writeInt(this.notificationGroupId);
			if (this.type == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.type.serialize(output);
			}
			output.writeLong(this.chatId);
			output.writeLong(this.notificationSettingsChatId);
			output.writeLong(this.notificationSoundId);
			output.writeInt(this.totalCount);
			if (this.addedNotifications == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.addedNotifications.length);
				for (int i = 0; i < this.addedNotifications.length; i++) {
					this.addedNotifications[i].serialize(output);
				}
			}
			if (this.removedNotificationIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.removedNotificationIds.length);
				for (int i = 0; i < this.removedNotificationIds.length; i++) {
					output.writeInt(this.removedNotificationIds[i]);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateNotificationGroup updateNotificationGroup = (UpdateNotificationGroup) o;
			if (this.notificationGroupId != updateNotificationGroup.notificationGroupId) {
				return false;
			}
			if (!Objects.equals(this.type, updateNotificationGroup.type)) {
				return false;
			}
			if (this.chatId != updateNotificationGroup.chatId) {
				return false;
			}
			if (this.notificationSettingsChatId != updateNotificationGroup.notificationSettingsChatId) {
				return false;
			}
			if (this.notificationSoundId != updateNotificationGroup.notificationSoundId) {
				return false;
			}
			if (this.totalCount != updateNotificationGroup.totalCount) {
				return false;
			}
			if (!Arrays.equals(this.addedNotifications, updateNotificationGroup.addedNotifications)) {
				return false;
			}
			if (!Arrays.equals(this.removedNotificationIds, updateNotificationGroup.removedNotificationIds)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.notificationGroupId);
			result = result * 31 + (this.type == null ? 0 : this.type.hashCode());
			result = result * 31 + (Arrays.hashCode(this.addedNotifications));
			result = result * 31 + (Arrays.hashCode(this.removedNotificationIds));
			return result;
		}
	}

	/**
	 * Contains active notifications that was shown on previous application
	 * launches. This update is sent only if the message database is used.
	 * In that case it comes once before any updateNotification and
	 * updateNotificationGroup update.
	**/
	public static final class UpdateActiveNotifications extends Update {


		/**
		 * Lists of active notification groups.
		**/
		public NotificationGroup[] groups;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1306672221;

		/**
		 * Contains active notifications that was shown on previous application launches. This update is sent only if the message database is used. In that case it comes once before any updateNotification and updateNotificationGroup update.
		**/
		public UpdateActiveNotifications() {}

		/**
		 * Contains active notifications that was shown on previous application launches. This update is sent only if the message database is used. In that case it comes once before any updateNotification and updateNotificationGroup update.
		 *
		 * @param groups Lists of active notification groups.
		**/
		public UpdateActiveNotifications(NotificationGroup[] groups) {
			this.groups = groups;
		}

		/**
		 * Contains active notifications that was shown on previous application launches. This update is sent only if the message database is used. In that case it comes once before any updateNotification and updateNotificationGroup update.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateActiveNotifications(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.groups = new NotificationGroup[input.readInt()];
				for (int i = 0; i < this.groups.length; i++) {
					if (NotificationGroup.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.groups[i] = new NotificationGroup(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateActiveNotifications.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateActiveNotifications.CONSTRUCTOR);
			if (this.groups == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.groups.length);
				for (int i = 0; i < this.groups.length; i++) {
					this.groups[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateActiveNotifications updateActiveNotifications = (UpdateActiveNotifications) o;
			if (!Arrays.equals(this.groups, updateActiveNotifications.groups)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.groups);
		}
	}

	/**
	 * Describes whether there are some pending notification updates. Can be
	 * used to prevent application from killing, while there are some
	 * pending notifications.
	**/
	public static final class UpdateHavePendingNotifications extends Update {


		/**
		 * True, if there are some delayed notification updates, which will be sent soon.
		**/
		public boolean haveDelayedNotifications;

		/**
		 * True, if there can be some yet unreceived notifications, which are being fetched from the server.
		**/
		public boolean haveUnreceivedNotifications;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 179233243;

		/**
		 * Describes whether there are some pending notification updates. Can be used to prevent application from killing, while there are some pending notifications.
		**/
		public UpdateHavePendingNotifications() {}

		/**
		 * Describes whether there are some pending notification updates. Can be used to prevent application from killing, while there are some pending notifications.
		 *
		 * @param haveDelayedNotifications True, if there are some delayed notification updates, which will be sent soon.
		 * @param haveUnreceivedNotifications True, if there can be some yet unreceived notifications, which are being fetched from the server.
		**/
		public UpdateHavePendingNotifications(boolean haveDelayedNotifications,
				boolean haveUnreceivedNotifications) {
			this.haveDelayedNotifications = haveDelayedNotifications;
			this.haveUnreceivedNotifications = haveUnreceivedNotifications;
		}

		/**
		 * Describes whether there are some pending notification updates. Can be used to prevent application from killing, while there are some pending notifications.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateHavePendingNotifications(DataInput input) throws IOException {
			this.haveDelayedNotifications = input.readBoolean();
			this.haveUnreceivedNotifications = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateHavePendingNotifications.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateHavePendingNotifications.CONSTRUCTOR);
			output.writeBoolean(this.haveDelayedNotifications);
			output.writeBoolean(this.haveUnreceivedNotifications);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateHavePendingNotifications updateHavePendingNotifications = (UpdateHavePendingNotifications) o;
			if (this.haveDelayedNotifications != updateHavePendingNotifications.haveDelayedNotifications) {
				return false;
			}
			if (this.haveUnreceivedNotifications != updateHavePendingNotifications.haveUnreceivedNotifications) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.haveDelayedNotifications);
			return result;
		}
	}

	/**
	 * Some messages were deleted.
	**/
	public static final class UpdateDeleteMessages extends Update {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Identifiers of the deleted messages.
		**/
		public long[] messageIds;

		/**
		 * True, if the messages are permanently deleted by a user (as opposed to just becoming inaccessible).
		**/
		public boolean isPermanent;

		/**
		 * True, if the messages are deleted only from the cache and can possibly be retrieved again in the future.
		**/
		public boolean fromCache;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1669252686;

		/**
		 * Some messages were deleted.
		**/
		public UpdateDeleteMessages() {}

		/**
		 * Some messages were deleted.
		 *
		 * @param chatId Chat identifier.
		 * @param messageIds Identifiers of the deleted messages.
		 * @param isPermanent True, if the messages are permanently deleted by a user (as opposed to just becoming inaccessible).
		 * @param fromCache True, if the messages are deleted only from the cache and can possibly be retrieved again in the future.
		**/
		public UpdateDeleteMessages(long chatId,
				long[] messageIds,
				boolean isPermanent,
				boolean fromCache) {
			this.chatId = chatId;
			this.messageIds = messageIds;
			this.isPermanent = isPermanent;
			this.fromCache = fromCache;
		}

		/**
		 * Some messages were deleted.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateDeleteMessages(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				this.messageIds = new long[input.readInt()];
				for (int i = 0; i < this.messageIds.length; i++) {
					this.messageIds[i] = input.readLong();
				}
			}
			this.isPermanent = input.readBoolean();
			this.fromCache = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateDeleteMessages.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateDeleteMessages.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.messageIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.messageIds.length);
				for (int i = 0; i < this.messageIds.length; i++) {
					output.writeLong(this.messageIds[i]);
				}
			}
			output.writeBoolean(this.isPermanent);
			output.writeBoolean(this.fromCache);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateDeleteMessages updateDeleteMessages = (UpdateDeleteMessages) o;
			if (this.chatId != updateDeleteMessages.chatId) {
				return false;
			}
			if (!Arrays.equals(this.messageIds, updateDeleteMessages.messageIds)) {
				return false;
			}
			if (this.isPermanent != updateDeleteMessages.isPermanent) {
				return false;
			}
			if (this.fromCache != updateDeleteMessages.fromCache) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (Arrays.hashCode(this.messageIds));
			return result;
		}
	}

	/**
	 * A message sender activity in the chat has changed.
	**/
	public static final class UpdateChatAction extends Update {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * If not 0, a message thread identifier in which the action was performed.
		**/
		public long messageThreadId;

		/**
		 * Identifier of a message sender performing the action.
		**/
		public MessageSender senderId;

		/**
		 * The action.
		**/
		public ChatAction action;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1698703832;

		/**
		 * A message sender activity in the chat has changed.
		**/
		public UpdateChatAction() {}

		/**
		 * A message sender activity in the chat has changed.
		 *
		 * @param chatId Chat identifier.
		 * @param messageThreadId If not 0, a message thread identifier in which the action was performed.
		 * @param senderId Identifier of a message sender performing the action.
		 * @param action The action.
		**/
		public UpdateChatAction(long chatId,
				long messageThreadId,
				MessageSender senderId,
				ChatAction action) {
			this.chatId = chatId;
			this.messageThreadId = messageThreadId;
			this.senderId = senderId;
			this.action = action;
		}

		/**
		 * A message sender activity in the chat has changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateChatAction(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageThreadId = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case MessageSenderUser.CONSTRUCTOR: this.senderId = new MessageSenderUser(input); break;
					case MessageSenderChat.CONSTRUCTOR: this.senderId = new MessageSenderChat(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ChatActionTyping.CONSTRUCTOR: this.action = new ChatActionTyping(input); break;
					case ChatActionRecordingVideo.CONSTRUCTOR: this.action = new ChatActionRecordingVideo(input); break;
					case ChatActionUploadingVideo.CONSTRUCTOR: this.action = new ChatActionUploadingVideo(input); break;
					case ChatActionRecordingVoiceNote.CONSTRUCTOR: this.action = new ChatActionRecordingVoiceNote(input); break;
					case ChatActionUploadingVoiceNote.CONSTRUCTOR: this.action = new ChatActionUploadingVoiceNote(input); break;
					case ChatActionUploadingPhoto.CONSTRUCTOR: this.action = new ChatActionUploadingPhoto(input); break;
					case ChatActionUploadingDocument.CONSTRUCTOR: this.action = new ChatActionUploadingDocument(input); break;
					case ChatActionChoosingSticker.CONSTRUCTOR: this.action = new ChatActionChoosingSticker(input); break;
					case ChatActionChoosingLocation.CONSTRUCTOR: this.action = new ChatActionChoosingLocation(input); break;
					case ChatActionChoosingContact.CONSTRUCTOR: this.action = new ChatActionChoosingContact(input); break;
					case ChatActionStartPlayingGame.CONSTRUCTOR: this.action = new ChatActionStartPlayingGame(input); break;
					case ChatActionRecordingVideoNote.CONSTRUCTOR: this.action = new ChatActionRecordingVideoNote(input); break;
					case ChatActionUploadingVideoNote.CONSTRUCTOR: this.action = new ChatActionUploadingVideoNote(input); break;
					case ChatActionWatchingAnimations.CONSTRUCTOR: this.action = new ChatActionWatchingAnimations(input); break;
					case ChatActionCancel.CONSTRUCTOR: this.action = new ChatActionCancel(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateChatAction.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateChatAction.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageThreadId);
			if (this.senderId == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.senderId.serialize(output);
			}
			if (this.action == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.action.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateChatAction updateChatAction = (UpdateChatAction) o;
			if (this.chatId != updateChatAction.chatId) {
				return false;
			}
			if (this.messageThreadId != updateChatAction.messageThreadId) {
				return false;
			}
			if (!Objects.equals(this.senderId, updateChatAction.senderId)) {
				return false;
			}
			if (!Objects.equals(this.action, updateChatAction.action)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.senderId == null ? 0 : this.senderId.hashCode());
			result = result * 31 + (this.action == null ? 0 : this.action.hashCode());
			return result;
		}
	}

	/**
	 * The user went online or offline.
	**/
	public static final class UpdateUserStatus extends Update {


		/**
		 * User identifier.
		**/
		public long userId;

		/**
		 * New status of the user.
		**/
		public UserStatus status;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 958468625;

		/**
		 * The user went online or offline.
		**/
		public UpdateUserStatus() {}

		/**
		 * The user went online or offline.
		 *
		 * @param userId User identifier.
		 * @param status New status of the user.
		**/
		public UpdateUserStatus(long userId, UserStatus status) {
			this.userId = userId;
			this.status = status;
		}

		/**
		 * The user went online or offline.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateUserStatus(DataInput input) throws IOException {
			this.userId = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case UserStatusEmpty.CONSTRUCTOR: this.status = new UserStatusEmpty(input); break;
					case UserStatusOnline.CONSTRUCTOR: this.status = new UserStatusOnline(input); break;
					case UserStatusOffline.CONSTRUCTOR: this.status = new UserStatusOffline(input); break;
					case UserStatusRecently.CONSTRUCTOR: this.status = new UserStatusRecently(input); break;
					case UserStatusLastWeek.CONSTRUCTOR: this.status = new UserStatusLastWeek(input); break;
					case UserStatusLastMonth.CONSTRUCTOR: this.status = new UserStatusLastMonth(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateUserStatus.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateUserStatus.CONSTRUCTOR);
			output.writeLong(this.userId);
			if (this.status == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.status.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateUserStatus updateUserStatus = (UpdateUserStatus) o;
			if (this.userId != updateUserStatus.userId) {
				return false;
			}
			if (!Objects.equals(this.status, updateUserStatus.status)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.userId);
			result = result * 31 + (this.status == null ? 0 : this.status.hashCode());
			return result;
		}
	}

	/**
	 * Some data of a user has changed. This update is guaranteed to come
	 * before the user identifier is returned to the application.
	**/
	public static final class UpdateUser extends Update {


		/**
		 * New data about the user.
		**/
		public User user;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1183394041;

		/**
		 * Some data of a user has changed. This update is guaranteed to come before the user identifier is returned to the application.
		**/
		public UpdateUser() {}

		/**
		 * Some data of a user has changed. This update is guaranteed to come before the user identifier is returned to the application.
		 *
		 * @param user New data about the user.
		**/
		public UpdateUser(User user) {
			this.user = user;
		}

		/**
		 * Some data of a user has changed. This update is guaranteed to come before the user identifier is returned to the application.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateUser(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (User.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.user = new User(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateUser.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateUser.CONSTRUCTOR);
			if (this.user == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.user.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateUser updateUser = (UpdateUser) o;
			if (!Objects.equals(this.user, updateUser.user)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.user == null ? 0 : this.user.hashCode();
		}
	}

	/**
	 * Some data of a user or a chat has changed. This update is guaranteed
	 * to come before the user or chat identifier is returned to the
	 * application.
	**/
	public static final class UpdateAccessHash extends Update {


		/**
		 * Access hash.
		**/
		public AccessHash accessHash;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1982152027;

		/**
		 * Some data of a user or a chat has changed. This update is guaranteed to come before the user or chat identifier is returned to the application.
		**/
		public UpdateAccessHash() {}

		/**
		 * Some data of a user or a chat has changed. This update is guaranteed to come before the user or chat identifier is returned to the application.
		 *
		 * @param accessHash Access hash.
		**/
		public UpdateAccessHash(AccessHash accessHash) {
			this.accessHash = accessHash;
		}

		/**
		 * Some data of a user or a chat has changed. This update is guaranteed to come before the user or chat identifier is returned to the application.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateAccessHash(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (AccessHash.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.accessHash = new AccessHash(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateAccessHash.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateAccessHash.CONSTRUCTOR);
			if (this.accessHash == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.accessHash.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateAccessHash updateAccessHash = (UpdateAccessHash) o;
			if (!Objects.equals(this.accessHash, updateAccessHash.accessHash)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.accessHash == null ? 0 : this.accessHash.hashCode();
		}
	}

	/**
	 * Some data of a basic group has changed. This update is guaranteed to
	 * come before the basic group identifier is returned to the
	 * application.
	**/
	public static final class UpdateBasicGroup extends Update {


		/**
		 * New data about the group.
		**/
		public BasicGroup basicGroup;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1003239581;

		/**
		 * Some data of a basic group has changed. This update is guaranteed to come before the basic group identifier is returned to the application.
		**/
		public UpdateBasicGroup() {}

		/**
		 * Some data of a basic group has changed. This update is guaranteed to come before the basic group identifier is returned to the application.
		 *
		 * @param basicGroup New data about the group.
		**/
		public UpdateBasicGroup(BasicGroup basicGroup) {
			this.basicGroup = basicGroup;
		}

		/**
		 * Some data of a basic group has changed. This update is guaranteed to come before the basic group identifier is returned to the application.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateBasicGroup(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (BasicGroup.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.basicGroup = new BasicGroup(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateBasicGroup.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateBasicGroup.CONSTRUCTOR);
			if (this.basicGroup == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.basicGroup.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateBasicGroup updateBasicGroup = (UpdateBasicGroup) o;
			if (!Objects.equals(this.basicGroup, updateBasicGroup.basicGroup)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.basicGroup == null ? 0 : this.basicGroup.hashCode();
		}
	}

	/**
	 * Some data of a supergroup or a channel has changed. This update is
	 * guaranteed to come before the supergroup identifier is returned to
	 * the application.
	**/
	public static final class UpdateSupergroup extends Update {


		/**
		 * New data about the supergroup.
		**/
		public Supergroup supergroup;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -76782300;

		/**
		 * Some data of a supergroup or a channel has changed. This update is guaranteed to come before the supergroup identifier is returned to the application.
		**/
		public UpdateSupergroup() {}

		/**
		 * Some data of a supergroup or a channel has changed. This update is guaranteed to come before the supergroup identifier is returned to the application.
		 *
		 * @param supergroup New data about the supergroup.
		**/
		public UpdateSupergroup(Supergroup supergroup) {
			this.supergroup = supergroup;
		}

		/**
		 * Some data of a supergroup or a channel has changed. This update is guaranteed to come before the supergroup identifier is returned to the application.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateSupergroup(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Supergroup.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.supergroup = new Supergroup(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateSupergroup.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateSupergroup.CONSTRUCTOR);
			if (this.supergroup == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.supergroup.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateSupergroup updateSupergroup = (UpdateSupergroup) o;
			if (!Objects.equals(this.supergroup, updateSupergroup.supergroup)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.supergroup == null ? 0 : this.supergroup.hashCode();
		}
	}

	/**
	 * Some data of a secret chat has changed. This update is guaranteed to
	 * come before the secret chat identifier is returned to the
	 * application.
	**/
	public static final class UpdateSecretChat extends Update {


		/**
		 * New data about the secret chat.
		**/
		public SecretChat secretChat;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1666903253;

		/**
		 * Some data of a secret chat has changed. This update is guaranteed to come before the secret chat identifier is returned to the application.
		**/
		public UpdateSecretChat() {}

		/**
		 * Some data of a secret chat has changed. This update is guaranteed to come before the secret chat identifier is returned to the application.
		 *
		 * @param secretChat New data about the secret chat.
		**/
		public UpdateSecretChat(SecretChat secretChat) {
			this.secretChat = secretChat;
		}

		/**
		 * Some data of a secret chat has changed. This update is guaranteed to come before the secret chat identifier is returned to the application.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateSecretChat(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (SecretChat.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.secretChat = new SecretChat(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateSecretChat.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateSecretChat.CONSTRUCTOR);
			if (this.secretChat == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.secretChat.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateSecretChat updateSecretChat = (UpdateSecretChat) o;
			if (!Objects.equals(this.secretChat, updateSecretChat.secretChat)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.secretChat == null ? 0 : this.secretChat.hashCode();
		}
	}

	/**
	 * Some data in userFullInfo has been changed.
	**/
	public static final class UpdateUserFullInfo extends Update {


		/**
		 * User identifier.
		**/
		public long userId;

		/**
		 * New full information about the user.
		**/
		public UserFullInfo userFullInfo;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -51197161;

		/**
		 * Some data in userFullInfo has been changed.
		**/
		public UpdateUserFullInfo() {}

		/**
		 * Some data in userFullInfo has been changed.
		 *
		 * @param userId User identifier.
		 * @param userFullInfo New full information about the user.
		**/
		public UpdateUserFullInfo(long userId, UserFullInfo userFullInfo) {
			this.userId = userId;
			this.userFullInfo = userFullInfo;
		}

		/**
		 * Some data in userFullInfo has been changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateUserFullInfo(DataInput input) throws IOException {
			this.userId = input.readLong();
			if (input.readBoolean()) {
				if (UserFullInfo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.userFullInfo = new UserFullInfo(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateUserFullInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateUserFullInfo.CONSTRUCTOR);
			output.writeLong(this.userId);
			if (this.userFullInfo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.userFullInfo.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateUserFullInfo updateUserFullInfo = (UpdateUserFullInfo) o;
			if (this.userId != updateUserFullInfo.userId) {
				return false;
			}
			if (!Objects.equals(this.userFullInfo, updateUserFullInfo.userFullInfo)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.userId);
			result = result * 31 + (this.userFullInfo == null ? 0 : this.userFullInfo.hashCode());
			return result;
		}
	}

	/**
	 * Some data in basicGroupFullInfo has been changed.
	**/
	public static final class UpdateBasicGroupFullInfo extends Update {


		/**
		 * Identifier of a basic group.
		**/
		public long basicGroupId;

		/**
		 * New full information about the group.
		**/
		public BasicGroupFullInfo basicGroupFullInfo;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1391881151;

		/**
		 * Some data in basicGroupFullInfo has been changed.
		**/
		public UpdateBasicGroupFullInfo() {}

		/**
		 * Some data in basicGroupFullInfo has been changed.
		 *
		 * @param basicGroupId Identifier of a basic group.
		 * @param basicGroupFullInfo New full information about the group.
		**/
		public UpdateBasicGroupFullInfo(long basicGroupId, BasicGroupFullInfo basicGroupFullInfo) {
			this.basicGroupId = basicGroupId;
			this.basicGroupFullInfo = basicGroupFullInfo;
		}

		/**
		 * Some data in basicGroupFullInfo has been changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateBasicGroupFullInfo(DataInput input) throws IOException {
			this.basicGroupId = input.readLong();
			if (input.readBoolean()) {
				if (BasicGroupFullInfo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.basicGroupFullInfo = new BasicGroupFullInfo(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateBasicGroupFullInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateBasicGroupFullInfo.CONSTRUCTOR);
			output.writeLong(this.basicGroupId);
			if (this.basicGroupFullInfo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.basicGroupFullInfo.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateBasicGroupFullInfo updateBasicGroupFullInfo = (UpdateBasicGroupFullInfo) o;
			if (this.basicGroupId != updateBasicGroupFullInfo.basicGroupId) {
				return false;
			}
			if (!Objects.equals(this.basicGroupFullInfo, updateBasicGroupFullInfo.basicGroupFullInfo)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.basicGroupId);
			result = result * 31 + (this.basicGroupFullInfo == null ? 0 : this.basicGroupFullInfo.hashCode());
			return result;
		}
	}

	/**
	 * Some data in supergroupFullInfo has been changed.
	**/
	public static final class UpdateSupergroupFullInfo extends Update {


		/**
		 * Identifier of the supergroup or channel.
		**/
		public long supergroupId;

		/**
		 * New full information about the supergroup.
		**/
		public SupergroupFullInfo supergroupFullInfo;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 435539214;

		/**
		 * Some data in supergroupFullInfo has been changed.
		**/
		public UpdateSupergroupFullInfo() {}

		/**
		 * Some data in supergroupFullInfo has been changed.
		 *
		 * @param supergroupId Identifier of the supergroup or channel.
		 * @param supergroupFullInfo New full information about the supergroup.
		**/
		public UpdateSupergroupFullInfo(long supergroupId, SupergroupFullInfo supergroupFullInfo) {
			this.supergroupId = supergroupId;
			this.supergroupFullInfo = supergroupFullInfo;
		}

		/**
		 * Some data in supergroupFullInfo has been changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateSupergroupFullInfo(DataInput input) throws IOException {
			this.supergroupId = input.readLong();
			if (input.readBoolean()) {
				if (SupergroupFullInfo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.supergroupFullInfo = new SupergroupFullInfo(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateSupergroupFullInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateSupergroupFullInfo.CONSTRUCTOR);
			output.writeLong(this.supergroupId);
			if (this.supergroupFullInfo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.supergroupFullInfo.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateSupergroupFullInfo updateSupergroupFullInfo = (UpdateSupergroupFullInfo) o;
			if (this.supergroupId != updateSupergroupFullInfo.supergroupId) {
				return false;
			}
			if (!Objects.equals(this.supergroupFullInfo, updateSupergroupFullInfo.supergroupFullInfo)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.supergroupId);
			result = result * 31 + (this.supergroupFullInfo == null ? 0 : this.supergroupFullInfo.hashCode());
			return result;
		}
	}

	/**
	 * A service notification from the server was received. Upon receiving
	 * this the application must show a popup with the content of the
	 * notification.
	**/
	public static final class UpdateServiceNotification extends Update {


		/**
		 * Notification type. If type begins with &quot;AUTH_KEY_DROP_&quot;, then two buttons &quot;Cancel&quot; and &quot;Log out&quot; must be shown under notification; if user presses the second, all local data must be destroyed using Destroy method.
		**/
		public String type;

		/**
		 * Notification content.
		**/
		public MessageContent content;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1318622637;

		/**
		 * A service notification from the server was received. Upon receiving this the application must show a popup with the content of the notification.
		**/
		public UpdateServiceNotification() {}

		/**
		 * A service notification from the server was received. Upon receiving this the application must show a popup with the content of the notification.
		 *
		 * @param type Notification type. If type begins with &quot;AUTH_KEY_DROP_&quot;, then two buttons &quot;Cancel&quot; and &quot;Log out&quot; must be shown under notification; if user presses the second, all local data must be destroyed using Destroy method.
		 * @param content Notification content.
		**/
		public UpdateServiceNotification(String type, MessageContent content) {
			this.type = type;
			this.content = content;
		}

		/**
		 * A service notification from the server was received. Upon receiving this the application must show a popup with the content of the notification.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateServiceNotification(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] typeTmp = new byte[input.readInt()];
				input.readFully(typeTmp);
				this.type = new String(typeTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case MessageText.CONSTRUCTOR: this.content = new MessageText(input); break;
					case MessageAnimation.CONSTRUCTOR: this.content = new MessageAnimation(input); break;
					case MessageAudio.CONSTRUCTOR: this.content = new MessageAudio(input); break;
					case MessageDocument.CONSTRUCTOR: this.content = new MessageDocument(input); break;
					case MessagePhoto.CONSTRUCTOR: this.content = new MessagePhoto(input); break;
					case MessageExpiredPhoto.CONSTRUCTOR: this.content = new MessageExpiredPhoto(input); break;
					case MessageSticker.CONSTRUCTOR: this.content = new MessageSticker(input); break;
					case MessageVideo.CONSTRUCTOR: this.content = new MessageVideo(input); break;
					case MessageExpiredVideo.CONSTRUCTOR: this.content = new MessageExpiredVideo(input); break;
					case MessageVideoNote.CONSTRUCTOR: this.content = new MessageVideoNote(input); break;
					case MessageVoiceNote.CONSTRUCTOR: this.content = new MessageVoiceNote(input); break;
					case MessageLocation.CONSTRUCTOR: this.content = new MessageLocation(input); break;
					case MessageVenue.CONSTRUCTOR: this.content = new MessageVenue(input); break;
					case MessageContact.CONSTRUCTOR: this.content = new MessageContact(input); break;
					case MessageAnimatedEmoji.CONSTRUCTOR: this.content = new MessageAnimatedEmoji(input); break;
					case MessageDice.CONSTRUCTOR: this.content = new MessageDice(input); break;
					case MessageGame.CONSTRUCTOR: this.content = new MessageGame(input); break;
					case MessagePoll.CONSTRUCTOR: this.content = new MessagePoll(input); break;
					case MessageInvoice.CONSTRUCTOR: this.content = new MessageInvoice(input); break;
					case MessageCall.CONSTRUCTOR: this.content = new MessageCall(input); break;
					case MessageVideoChatScheduled.CONSTRUCTOR: this.content = new MessageVideoChatScheduled(input); break;
					case MessageVideoChatStarted.CONSTRUCTOR: this.content = new MessageVideoChatStarted(input); break;
					case MessageVideoChatEnded.CONSTRUCTOR: this.content = new MessageVideoChatEnded(input); break;
					case MessageInviteVideoChatParticipants.CONSTRUCTOR: this.content = new MessageInviteVideoChatParticipants(input); break;
					case MessageBasicGroupChatCreate.CONSTRUCTOR: this.content = new MessageBasicGroupChatCreate(input); break;
					case MessageSupergroupChatCreate.CONSTRUCTOR: this.content = new MessageSupergroupChatCreate(input); break;
					case MessageChatChangeTitle.CONSTRUCTOR: this.content = new MessageChatChangeTitle(input); break;
					case MessageChatChangePhoto.CONSTRUCTOR: this.content = new MessageChatChangePhoto(input); break;
					case MessageChatDeletePhoto.CONSTRUCTOR: this.content = new MessageChatDeletePhoto(input); break;
					case MessageChatAddMembers.CONSTRUCTOR: this.content = new MessageChatAddMembers(input); break;
					case MessageChatJoinByLink.CONSTRUCTOR: this.content = new MessageChatJoinByLink(input); break;
					case MessageChatJoinByRequest.CONSTRUCTOR: this.content = new MessageChatJoinByRequest(input); break;
					case MessageChatDeleteMember.CONSTRUCTOR: this.content = new MessageChatDeleteMember(input); break;
					case MessageChatUpgradeTo.CONSTRUCTOR: this.content = new MessageChatUpgradeTo(input); break;
					case MessageChatUpgradeFrom.CONSTRUCTOR: this.content = new MessageChatUpgradeFrom(input); break;
					case MessagePinMessage.CONSTRUCTOR: this.content = new MessagePinMessage(input); break;
					case MessageScreenshotTaken.CONSTRUCTOR: this.content = new MessageScreenshotTaken(input); break;
					case MessageChatSetBackground.CONSTRUCTOR: this.content = new MessageChatSetBackground(input); break;
					case MessageChatSetTheme.CONSTRUCTOR: this.content = new MessageChatSetTheme(input); break;
					case MessageChatSetMessageAutoDeleteTime.CONSTRUCTOR: this.content = new MessageChatSetMessageAutoDeleteTime(input); break;
					case MessageForumTopicCreated.CONSTRUCTOR: this.content = new MessageForumTopicCreated(input); break;
					case MessageForumTopicEdited.CONSTRUCTOR: this.content = new MessageForumTopicEdited(input); break;
					case MessageForumTopicIsClosedToggled.CONSTRUCTOR: this.content = new MessageForumTopicIsClosedToggled(input); break;
					case MessageForumTopicIsHiddenToggled.CONSTRUCTOR: this.content = new MessageForumTopicIsHiddenToggled(input); break;
					case MessageSuggestProfilePhoto.CONSTRUCTOR: this.content = new MessageSuggestProfilePhoto(input); break;
					case MessageCustomServiceAction.CONSTRUCTOR: this.content = new MessageCustomServiceAction(input); break;
					case MessageGameScore.CONSTRUCTOR: this.content = new MessageGameScore(input); break;
					case MessagePaymentSuccessful.CONSTRUCTOR: this.content = new MessagePaymentSuccessful(input); break;
					case MessagePaymentSuccessfulBot.CONSTRUCTOR: this.content = new MessagePaymentSuccessfulBot(input); break;
					case MessageGiftedPremium.CONSTRUCTOR: this.content = new MessageGiftedPremium(input); break;
					case MessageContactRegistered.CONSTRUCTOR: this.content = new MessageContactRegistered(input); break;
					case MessageUserShared.CONSTRUCTOR: this.content = new MessageUserShared(input); break;
					case MessageChatShared.CONSTRUCTOR: this.content = new MessageChatShared(input); break;
					case MessageWebsiteConnected.CONSTRUCTOR: this.content = new MessageWebsiteConnected(input); break;
					case MessageBotWriteAccessAllowed.CONSTRUCTOR: this.content = new MessageBotWriteAccessAllowed(input); break;
					case MessageWebAppDataSent.CONSTRUCTOR: this.content = new MessageWebAppDataSent(input); break;
					case MessageWebAppDataReceived.CONSTRUCTOR: this.content = new MessageWebAppDataReceived(input); break;
					case MessagePassportDataSent.CONSTRUCTOR: this.content = new MessagePassportDataSent(input); break;
					case MessagePassportDataReceived.CONSTRUCTOR: this.content = new MessagePassportDataReceived(input); break;
					case MessageProximityAlertTriggered.CONSTRUCTOR: this.content = new MessageProximityAlertTriggered(input); break;
					case MessageUnsupported.CONSTRUCTOR: this.content = new MessageUnsupported(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateServiceNotification.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateServiceNotification.CONSTRUCTOR);
			if (this.type == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] typeTmp = this.type.getBytes(StandardCharsets.UTF_8);
				output.writeInt(typeTmp.length);
				output.write(typeTmp);
			}
			if (this.content == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.content.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateServiceNotification updateServiceNotification = (UpdateServiceNotification) o;
			if (this.type != updateServiceNotification.type) {
				return false;
			}
			if (!Objects.equals(this.content, updateServiceNotification.content)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.type == null ? 0 : this.type.hashCode();
			result = result * 31 + (this.content == null ? 0 : this.content.hashCode());
			return result;
		}
	}

	/**
	 * Information about a file was updated.
	**/
	public static final class UpdateFile extends Update {


		/**
		 * New data about the file.
		**/
		public File file;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 114132831;

		/**
		 * Information about a file was updated.
		**/
		public UpdateFile() {}

		/**
		 * Information about a file was updated.
		 *
		 * @param file New data about the file.
		**/
		public UpdateFile(File file) {
			this.file = file;
		}

		/**
		 * Information about a file was updated.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateFile(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (File.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.file = new File(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateFile.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateFile.CONSTRUCTOR);
			if (this.file == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.file.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateFile updateFile = (UpdateFile) o;
			if (!Objects.equals(this.file, updateFile.file)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.file == null ? 0 : this.file.hashCode();
		}
	}

	/**
	 * The file generation process needs to be started by the application.
	**/
	public static final class UpdateFileGenerationStart extends Update {


		/**
		 * Unique identifier for the generation process.
		**/
		public long generationId;

		/**
		 * The path to a file from which a new file is generated; may be empty.
		**/
		public String originalPath;

		/**
		 * The path to a file that must be created and where the new file is generated.
		**/
		public String destinationPath;

		/**
		 * String specifying the conversion applied to the original file. If conversion is &quot;#url#&quot; than originalPath contains an HTTP/HTTPS URL of a file, which must be downloaded by the application.
		**/
		public String conversion;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 216817388;

		/**
		 * The file generation process needs to be started by the application.
		**/
		public UpdateFileGenerationStart() {}

		/**
		 * The file generation process needs to be started by the application.
		 *
		 * @param generationId Unique identifier for the generation process.
		 * @param originalPath The path to a file from which a new file is generated; may be empty.
		 * @param destinationPath The path to a file that must be created and where the new file is generated.
		 * @param conversion String specifying the conversion applied to the original file. If conversion is &quot;#url#&quot; than originalPath contains an HTTP/HTTPS URL of a file, which must be downloaded by the application.
		**/
		public UpdateFileGenerationStart(long generationId,
				String originalPath,
				String destinationPath,
				String conversion) {
			this.generationId = generationId;
			this.originalPath = originalPath;
			this.destinationPath = destinationPath;
			this.conversion = conversion;
		}

		/**
		 * The file generation process needs to be started by the application.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateFileGenerationStart(DataInput input) throws IOException {
			this.generationId = input.readLong();
			if (input.readBoolean()) {
				byte[] originalPathTmp = new byte[input.readInt()];
				input.readFully(originalPathTmp);
				this.originalPath = new String(originalPathTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] destinationPathTmp = new byte[input.readInt()];
				input.readFully(destinationPathTmp);
				this.destinationPath = new String(destinationPathTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] conversionTmp = new byte[input.readInt()];
				input.readFully(conversionTmp);
				this.conversion = new String(conversionTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateFileGenerationStart.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateFileGenerationStart.CONSTRUCTOR);
			output.writeLong(this.generationId);
			if (this.originalPath == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] originalPathTmp = this.originalPath.getBytes(StandardCharsets.UTF_8);
				output.writeInt(originalPathTmp.length);
				output.write(originalPathTmp);
			}
			if (this.destinationPath == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] destinationPathTmp = this.destinationPath.getBytes(StandardCharsets.UTF_8);
				output.writeInt(destinationPathTmp.length);
				output.write(destinationPathTmp);
			}
			if (this.conversion == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] conversionTmp = this.conversion.getBytes(StandardCharsets.UTF_8);
				output.writeInt(conversionTmp.length);
				output.write(conversionTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateFileGenerationStart updateFileGenerationStart = (UpdateFileGenerationStart) o;
			if (this.generationId != updateFileGenerationStart.generationId) {
				return false;
			}
			if (this.originalPath != updateFileGenerationStart.originalPath) {
				return false;
			}
			if (this.destinationPath != updateFileGenerationStart.destinationPath) {
				return false;
			}
			if (this.conversion != updateFileGenerationStart.conversion) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.generationId);
			result = result * 31 + (this.originalPath == null ? 0 : this.originalPath.hashCode());
			result = result * 31 + (this.destinationPath == null ? 0 : this.destinationPath.hashCode());
			result = result * 31 + (this.conversion == null ? 0 : this.conversion.hashCode());
			return result;
		}
	}

	/**
	 * File generation is no longer needed.
	**/
	public static final class UpdateFileGenerationStop extends Update {


		/**
		 * Unique identifier for the generation process.
		**/
		public long generationId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1894449685;

		/**
		 * File generation is no longer needed.
		**/
		public UpdateFileGenerationStop() {}

		/**
		 * File generation is no longer needed.
		 *
		 * @param generationId Unique identifier for the generation process.
		**/
		public UpdateFileGenerationStop(long generationId) {
			this.generationId = generationId;
		}

		/**
		 * File generation is no longer needed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateFileGenerationStop(DataInput input) throws IOException {
			this.generationId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateFileGenerationStop.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateFileGenerationStop.CONSTRUCTOR);
			output.writeLong(this.generationId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateFileGenerationStop updateFileGenerationStop = (UpdateFileGenerationStop) o;
			if (this.generationId != updateFileGenerationStop.generationId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.generationId);
		}
	}

	/**
	 * The state of the file download list has changed.
	**/
	public static final class UpdateFileDownloads extends Update {


		/**
		 * Total size of files in the file download list, in bytes.
		**/
		public long totalSize;

		/**
		 * Total number of files in the file download list.
		**/
		public int totalCount;

		/**
		 * Total downloaded size of files in the file download list, in bytes.
		**/
		public long downloadedSize;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -389213497;

		/**
		 * The state of the file download list has changed.
		**/
		public UpdateFileDownloads() {}

		/**
		 * The state of the file download list has changed.
		 *
		 * @param totalSize Total size of files in the file download list, in bytes.
		 * @param totalCount Total number of files in the file download list.
		 * @param downloadedSize Total downloaded size of files in the file download list, in bytes.
		**/
		public UpdateFileDownloads(long totalSize, int totalCount, long downloadedSize) {
			this.totalSize = totalSize;
			this.totalCount = totalCount;
			this.downloadedSize = downloadedSize;
		}

		/**
		 * The state of the file download list has changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateFileDownloads(DataInput input) throws IOException {
			this.totalSize = input.readLong();
			this.totalCount = input.readInt();
			this.downloadedSize = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateFileDownloads.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateFileDownloads.CONSTRUCTOR);
			output.writeLong(this.totalSize);
			output.writeInt(this.totalCount);
			output.writeLong(this.downloadedSize);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateFileDownloads updateFileDownloads = (UpdateFileDownloads) o;
			if (this.totalSize != updateFileDownloads.totalSize) {
				return false;
			}
			if (this.totalCount != updateFileDownloads.totalCount) {
				return false;
			}
			if (this.downloadedSize != updateFileDownloads.downloadedSize) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.totalSize);
			return result;
		}
	}

	/**
	 * A file was added to the file download list. This update is sent only
	 * after file download list is loaded for the first time.
	**/
	public static final class UpdateFileAddedToDownloads extends Update {


		/**
		 * The added file download.
		**/
		public FileDownload fileDownload;

		/**
		 * New number of being downloaded and recently downloaded files found.
		**/
		public DownloadedFileCounts counts;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1609929242;

		/**
		 * A file was added to the file download list. This update is sent only after file download list is loaded for the first time.
		**/
		public UpdateFileAddedToDownloads() {}

		/**
		 * A file was added to the file download list. This update is sent only after file download list is loaded for the first time.
		 *
		 * @param fileDownload The added file download.
		 * @param counts New number of being downloaded and recently downloaded files found.
		**/
		public UpdateFileAddedToDownloads(FileDownload fileDownload, DownloadedFileCounts counts) {
			this.fileDownload = fileDownload;
			this.counts = counts;
		}

		/**
		 * A file was added to the file download list. This update is sent only after file download list is loaded for the first time.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateFileAddedToDownloads(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (FileDownload.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.fileDownload = new FileDownload(input);
			}
			if (input.readBoolean()) {
				if (DownloadedFileCounts.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.counts = new DownloadedFileCounts(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateFileAddedToDownloads.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateFileAddedToDownloads.CONSTRUCTOR);
			if (this.fileDownload == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.fileDownload.serialize(output);
			}
			if (this.counts == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.counts.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateFileAddedToDownloads updateFileAddedToDownloads = (UpdateFileAddedToDownloads) o;
			if (!Objects.equals(this.fileDownload, updateFileAddedToDownloads.fileDownload)) {
				return false;
			}
			if (!Objects.equals(this.counts, updateFileAddedToDownloads.counts)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.fileDownload == null ? 0 : this.fileDownload.hashCode();
			result = result * 31 + (this.counts == null ? 0 : this.counts.hashCode());
			return result;
		}
	}

	/**
	 * A file download was changed. This update is sent only after file
	 * download list is loaded for the first time.
	**/
	public static final class UpdateFileDownload extends Update {


		/**
		 * File identifier.
		**/
		public int fileId;

		/**
		 * Point in time (Unix timestamp) when the file downloading was completed; 0 if the file downloading isn&#039;t completed.
		**/
		public int completeDate;

		/**
		 * True, if downloading of the file is paused.
		**/
		public boolean isPaused;

		/**
		 * New number of being downloaded and recently downloaded files found.
		**/
		public DownloadedFileCounts counts;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 875529162;

		/**
		 * A file download was changed. This update is sent only after file download list is loaded for the first time.
		**/
		public UpdateFileDownload() {}

		/**
		 * A file download was changed. This update is sent only after file download list is loaded for the first time.
		 *
		 * @param fileId File identifier.
		 * @param completeDate Point in time (Unix timestamp) when the file downloading was completed; 0 if the file downloading isn&#039;t completed.
		 * @param isPaused True, if downloading of the file is paused.
		 * @param counts New number of being downloaded and recently downloaded files found.
		**/
		public UpdateFileDownload(int fileId,
				int completeDate,
				boolean isPaused,
				DownloadedFileCounts counts) {
			this.fileId = fileId;
			this.completeDate = completeDate;
			this.isPaused = isPaused;
			this.counts = counts;
		}

		/**
		 * A file download was changed. This update is sent only after file download list is loaded for the first time.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateFileDownload(DataInput input) throws IOException {
			this.fileId = input.readInt();
			this.completeDate = input.readInt();
			this.isPaused = input.readBoolean();
			if (input.readBoolean()) {
				if (DownloadedFileCounts.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.counts = new DownloadedFileCounts(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateFileDownload.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateFileDownload.CONSTRUCTOR);
			output.writeInt(this.fileId);
			output.writeInt(this.completeDate);
			output.writeBoolean(this.isPaused);
			if (this.counts == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.counts.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateFileDownload updateFileDownload = (UpdateFileDownload) o;
			if (this.fileId != updateFileDownload.fileId) {
				return false;
			}
			if (this.completeDate != updateFileDownload.completeDate) {
				return false;
			}
			if (this.isPaused != updateFileDownload.isPaused) {
				return false;
			}
			if (!Objects.equals(this.counts, updateFileDownload.counts)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.fileId);
			result = result * 31 + (this.counts == null ? 0 : this.counts.hashCode());
			return result;
		}
	}

	/**
	 * A file was removed from the file download list. This update is sent
	 * only after file download list is loaded for the first time.
	**/
	public static final class UpdateFileRemovedFromDownloads extends Update {


		/**
		 * File identifier.
		**/
		public int fileId;

		/**
		 * New number of being downloaded and recently downloaded files found.
		**/
		public DownloadedFileCounts counts;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1853625576;

		/**
		 * A file was removed from the file download list. This update is sent only after file download list is loaded for the first time.
		**/
		public UpdateFileRemovedFromDownloads() {}

		/**
		 * A file was removed from the file download list. This update is sent only after file download list is loaded for the first time.
		 *
		 * @param fileId File identifier.
		 * @param counts New number of being downloaded and recently downloaded files found.
		**/
		public UpdateFileRemovedFromDownloads(int fileId, DownloadedFileCounts counts) {
			this.fileId = fileId;
			this.counts = counts;
		}

		/**
		 * A file was removed from the file download list. This update is sent only after file download list is loaded for the first time.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateFileRemovedFromDownloads(DataInput input) throws IOException {
			this.fileId = input.readInt();
			if (input.readBoolean()) {
				if (DownloadedFileCounts.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.counts = new DownloadedFileCounts(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateFileRemovedFromDownloads.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateFileRemovedFromDownloads.CONSTRUCTOR);
			output.writeInt(this.fileId);
			if (this.counts == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.counts.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateFileRemovedFromDownloads updateFileRemovedFromDownloads = (UpdateFileRemovedFromDownloads) o;
			if (this.fileId != updateFileRemovedFromDownloads.fileId) {
				return false;
			}
			if (!Objects.equals(this.counts, updateFileRemovedFromDownloads.counts)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.fileId);
			result = result * 31 + (this.counts == null ? 0 : this.counts.hashCode());
			return result;
		}
	}

	/**
	 * New call was created or information about a call was updated.
	**/
	public static final class UpdateCall extends Update {


		/**
		 * New data about a call.
		**/
		public Call call;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1337184477;

		/**
		 * New call was created or information about a call was updated.
		**/
		public UpdateCall() {}

		/**
		 * New call was created or information about a call was updated.
		 *
		 * @param call New data about a call.
		**/
		public UpdateCall(Call call) {
			this.call = call;
		}

		/**
		 * New call was created or information about a call was updated.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateCall(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Call.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.call = new Call(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateCall.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateCall.CONSTRUCTOR);
			if (this.call == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.call.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateCall updateCall = (UpdateCall) o;
			if (!Objects.equals(this.call, updateCall.call)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.call == null ? 0 : this.call.hashCode();
		}
	}

	/**
	 * Information about a group call was updated.
	**/
	public static final class UpdateGroupCall extends Update {


		/**
		 * New data about a group call.
		**/
		public GroupCall groupCall;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 808603136;

		/**
		 * Information about a group call was updated.
		**/
		public UpdateGroupCall() {}

		/**
		 * Information about a group call was updated.
		 *
		 * @param groupCall New data about a group call.
		**/
		public UpdateGroupCall(GroupCall groupCall) {
			this.groupCall = groupCall;
		}

		/**
		 * Information about a group call was updated.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateGroupCall(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (GroupCall.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.groupCall = new GroupCall(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateGroupCall.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateGroupCall.CONSTRUCTOR);
			if (this.groupCall == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.groupCall.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateGroupCall updateGroupCall = (UpdateGroupCall) o;
			if (!Objects.equals(this.groupCall, updateGroupCall.groupCall)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.groupCall == null ? 0 : this.groupCall.hashCode();
		}
	}

	/**
	 * Information about a group call participant was changed. The updates
	 * are sent only after the group call is received through getGroupCall
	 * and only if the call is joined or being joined.
	**/
	public static final class UpdateGroupCallParticipant extends Update {


		/**
		 * Identifier of group call.
		**/
		public int groupCallId;

		/**
		 * New data about a participant.
		**/
		public GroupCallParticipant participant;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -803128071;

		/**
		 * Information about a group call participant was changed. The updates are sent only after the group call is received through getGroupCall and only if the call is joined or being joined.
		**/
		public UpdateGroupCallParticipant() {}

		/**
		 * Information about a group call participant was changed. The updates are sent only after the group call is received through getGroupCall and only if the call is joined or being joined.
		 *
		 * @param groupCallId Identifier of group call.
		 * @param participant New data about a participant.
		**/
		public UpdateGroupCallParticipant(int groupCallId, GroupCallParticipant participant) {
			this.groupCallId = groupCallId;
			this.participant = participant;
		}

		/**
		 * Information about a group call participant was changed. The updates are sent only after the group call is received through getGroupCall and only if the call is joined or being joined.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateGroupCallParticipant(DataInput input) throws IOException {
			this.groupCallId = input.readInt();
			if (input.readBoolean()) {
				if (GroupCallParticipant.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.participant = new GroupCallParticipant(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateGroupCallParticipant.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateGroupCallParticipant.CONSTRUCTOR);
			output.writeInt(this.groupCallId);
			if (this.participant == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.participant.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateGroupCallParticipant updateGroupCallParticipant = (UpdateGroupCallParticipant) o;
			if (this.groupCallId != updateGroupCallParticipant.groupCallId) {
				return false;
			}
			if (!Objects.equals(this.participant, updateGroupCallParticipant.participant)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.groupCallId);
			result = result * 31 + (this.participant == null ? 0 : this.participant.hashCode());
			return result;
		}
	}

	/**
	 * New call signaling data arrived.
	**/
	public static final class UpdateNewCallSignalingData extends Update {


		/**
		 * The call identifier.
		**/
		public int callId;

		/**
		 * The data.
		**/
		public byte[] data;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 583634317;

		/**
		 * New call signaling data arrived.
		**/
		public UpdateNewCallSignalingData() {}

		/**
		 * New call signaling data arrived.
		 *
		 * @param callId The call identifier.
		 * @param data The data.
		**/
		public UpdateNewCallSignalingData(int callId, byte[] data) {
			this.callId = callId;
			this.data = data;
		}

		/**
		 * New call signaling data arrived.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateNewCallSignalingData(DataInput input) throws IOException {
			this.callId = input.readInt();
			if (input.readBoolean()) {
				this.data = new byte[input.readInt()];
				input.readFully(this.data);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateNewCallSignalingData.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateNewCallSignalingData.CONSTRUCTOR);
			output.writeInt(this.callId);
			if (this.data == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.data.length);
				output.write(this.data);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateNewCallSignalingData updateNewCallSignalingData = (UpdateNewCallSignalingData) o;
			if (this.callId != updateNewCallSignalingData.callId) {
				return false;
			}
			if (this.data != updateNewCallSignalingData.data) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.callId);
			result = result * 31 + (Arrays.hashCode(this.data));
			return result;
		}
	}

	/**
	 * Some privacy setting rules have been changed.
	**/
	public static final class UpdateUserPrivacySettingRules extends Update {


		/**
		 * The privacy setting.
		**/
		public UserPrivacySetting setting;

		/**
		 * New privacy rules.
		**/
		public UserPrivacySettingRules rules;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -912960778;

		/**
		 * Some privacy setting rules have been changed.
		**/
		public UpdateUserPrivacySettingRules() {}

		/**
		 * Some privacy setting rules have been changed.
		 *
		 * @param setting The privacy setting.
		 * @param rules New privacy rules.
		**/
		public UpdateUserPrivacySettingRules(UserPrivacySetting setting, UserPrivacySettingRules rules) {
			this.setting = setting;
			this.rules = rules;
		}

		/**
		 * Some privacy setting rules have been changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateUserPrivacySettingRules(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case UserPrivacySettingShowStatus.CONSTRUCTOR: this.setting = new UserPrivacySettingShowStatus(input); break;
					case UserPrivacySettingShowProfilePhoto.CONSTRUCTOR: this.setting = new UserPrivacySettingShowProfilePhoto(input); break;
					case UserPrivacySettingShowLinkInForwardedMessages.CONSTRUCTOR: this.setting = new UserPrivacySettingShowLinkInForwardedMessages(input); break;
					case UserPrivacySettingShowPhoneNumber.CONSTRUCTOR: this.setting = new UserPrivacySettingShowPhoneNumber(input); break;
					case UserPrivacySettingAllowChatInvites.CONSTRUCTOR: this.setting = new UserPrivacySettingAllowChatInvites(input); break;
					case UserPrivacySettingAllowCalls.CONSTRUCTOR: this.setting = new UserPrivacySettingAllowCalls(input); break;
					case UserPrivacySettingAllowPeerToPeerCalls.CONSTRUCTOR: this.setting = new UserPrivacySettingAllowPeerToPeerCalls(input); break;
					case UserPrivacySettingAllowFindingByPhoneNumber.CONSTRUCTOR: this.setting = new UserPrivacySettingAllowFindingByPhoneNumber(input); break;
					case UserPrivacySettingAllowPrivateVoiceAndVideoNoteMessages.CONSTRUCTOR: this.setting = new UserPrivacySettingAllowPrivateVoiceAndVideoNoteMessages(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				if (UserPrivacySettingRules.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.rules = new UserPrivacySettingRules(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateUserPrivacySettingRules.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateUserPrivacySettingRules.CONSTRUCTOR);
			if (this.setting == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.setting.serialize(output);
			}
			if (this.rules == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.rules.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateUserPrivacySettingRules updateUserPrivacySettingRules = (UpdateUserPrivacySettingRules) o;
			if (!Objects.equals(this.setting, updateUserPrivacySettingRules.setting)) {
				return false;
			}
			if (!Objects.equals(this.rules, updateUserPrivacySettingRules.rules)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.setting == null ? 0 : this.setting.hashCode();
			result = result * 31 + (this.rules == null ? 0 : this.rules.hashCode());
			return result;
		}
	}

	/**
	 * Number of unread messages in a chat list has changed. This update is
	 * sent only if the message database is used.
	**/
	public static final class UpdateUnreadMessageCount extends Update {


		/**
		 * The chat list with changed number of unread messages.
		**/
		public ChatList chatList;

		/**
		 * Total number of unread messages.
		**/
		public int unreadCount;

		/**
		 * Total number of unread messages in unmuted chats.
		**/
		public int unreadUnmutedCount;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 78987721;

		/**
		 * Number of unread messages in a chat list has changed. This update is sent only if the message database is used.
		**/
		public UpdateUnreadMessageCount() {}

		/**
		 * Number of unread messages in a chat list has changed. This update is sent only if the message database is used.
		 *
		 * @param chatList The chat list with changed number of unread messages.
		 * @param unreadCount Total number of unread messages.
		 * @param unreadUnmutedCount Total number of unread messages in unmuted chats.
		**/
		public UpdateUnreadMessageCount(ChatList chatList, int unreadCount, int unreadUnmutedCount) {
			this.chatList = chatList;
			this.unreadCount = unreadCount;
			this.unreadUnmutedCount = unreadUnmutedCount;
		}

		/**
		 * Number of unread messages in a chat list has changed. This update is sent only if the message database is used.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateUnreadMessageCount(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ChatListMain.CONSTRUCTOR: this.chatList = new ChatListMain(input); break;
					case ChatListArchive.CONSTRUCTOR: this.chatList = new ChatListArchive(input); break;
					case ChatListFolder.CONSTRUCTOR: this.chatList = new ChatListFolder(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.unreadCount = input.readInt();
			this.unreadUnmutedCount = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateUnreadMessageCount.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateUnreadMessageCount.CONSTRUCTOR);
			if (this.chatList == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.chatList.serialize(output);
			}
			output.writeInt(this.unreadCount);
			output.writeInt(this.unreadUnmutedCount);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateUnreadMessageCount updateUnreadMessageCount = (UpdateUnreadMessageCount) o;
			if (!Objects.equals(this.chatList, updateUnreadMessageCount.chatList)) {
				return false;
			}
			if (this.unreadCount != updateUnreadMessageCount.unreadCount) {
				return false;
			}
			if (this.unreadUnmutedCount != updateUnreadMessageCount.unreadUnmutedCount) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.unreadCount);
			result = result * 31 + (this.chatList == null ? 0 : this.chatList.hashCode());
			return result;
		}
	}

	/**
	 * Number of unread chats, i.e. with unread messages or marked as
	 * unread, has changed. This update is sent only if the message database
	 * is used.
	**/
	public static final class UpdateUnreadChatCount extends Update {


		/**
		 * The chat list with changed number of unread messages.
		**/
		public ChatList chatList;

		/**
		 * Approximate total number of chats in the chat list.
		**/
		public int totalCount;

		/**
		 * Total number of unread chats.
		**/
		public int unreadCount;

		/**
		 * Total number of unread unmuted chats.
		**/
		public int unreadUnmutedCount;

		/**
		 * Total number of chats marked as unread.
		**/
		public int markedAsUnreadCount;

		/**
		 * Total number of unmuted chats marked as unread.
		**/
		public int markedAsUnreadUnmutedCount;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1994494530;

		/**
		 * Number of unread chats, i.e. with unread messages or marked as unread, has changed. This update is sent only if the message database is used.
		**/
		public UpdateUnreadChatCount() {}

		/**
		 * Number of unread chats, i.e. with unread messages or marked as unread, has changed. This update is sent only if the message database is used.
		 *
		 * @param chatList The chat list with changed number of unread messages.
		 * @param totalCount Approximate total number of chats in the chat list.
		 * @param unreadCount Total number of unread chats.
		 * @param unreadUnmutedCount Total number of unread unmuted chats.
		 * @param markedAsUnreadCount Total number of chats marked as unread.
		 * @param markedAsUnreadUnmutedCount Total number of unmuted chats marked as unread.
		**/
		public UpdateUnreadChatCount(ChatList chatList,
				int totalCount,
				int unreadCount,
				int unreadUnmutedCount,
				int markedAsUnreadCount,
				int markedAsUnreadUnmutedCount) {
			this.chatList = chatList;
			this.totalCount = totalCount;
			this.unreadCount = unreadCount;
			this.unreadUnmutedCount = unreadUnmutedCount;
			this.markedAsUnreadCount = markedAsUnreadCount;
			this.markedAsUnreadUnmutedCount = markedAsUnreadUnmutedCount;
		}

		/**
		 * Number of unread chats, i.e. with unread messages or marked as unread, has changed. This update is sent only if the message database is used.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateUnreadChatCount(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ChatListMain.CONSTRUCTOR: this.chatList = new ChatListMain(input); break;
					case ChatListArchive.CONSTRUCTOR: this.chatList = new ChatListArchive(input); break;
					case ChatListFolder.CONSTRUCTOR: this.chatList = new ChatListFolder(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.totalCount = input.readInt();
			this.unreadCount = input.readInt();
			this.unreadUnmutedCount = input.readInt();
			this.markedAsUnreadCount = input.readInt();
			this.markedAsUnreadUnmutedCount = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateUnreadChatCount.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateUnreadChatCount.CONSTRUCTOR);
			if (this.chatList == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.chatList.serialize(output);
			}
			output.writeInt(this.totalCount);
			output.writeInt(this.unreadCount);
			output.writeInt(this.unreadUnmutedCount);
			output.writeInt(this.markedAsUnreadCount);
			output.writeInt(this.markedAsUnreadUnmutedCount);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateUnreadChatCount updateUnreadChatCount = (UpdateUnreadChatCount) o;
			if (!Objects.equals(this.chatList, updateUnreadChatCount.chatList)) {
				return false;
			}
			if (this.totalCount != updateUnreadChatCount.totalCount) {
				return false;
			}
			if (this.unreadCount != updateUnreadChatCount.unreadCount) {
				return false;
			}
			if (this.unreadUnmutedCount != updateUnreadChatCount.unreadUnmutedCount) {
				return false;
			}
			if (this.markedAsUnreadCount != updateUnreadChatCount.markedAsUnreadCount) {
				return false;
			}
			if (this.markedAsUnreadUnmutedCount != updateUnreadChatCount.markedAsUnreadUnmutedCount) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.totalCount);
			result = result * 31 + (this.chatList == null ? 0 : this.chatList.hashCode());
			return result;
		}
	}

	/**
	 * An option changed its value.
	**/
	public static final class UpdateOption extends Update {


		/**
		 * The option name.
		**/
		public String name;

		/**
		 * The new option value.
		**/
		public OptionValue value;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 900822020;

		/**
		 * An option changed its value.
		**/
		public UpdateOption() {}

		/**
		 * An option changed its value.
		 *
		 * @param name The option name.
		 * @param value The new option value.
		**/
		public UpdateOption(String name, OptionValue value) {
			this.name = name;
			this.value = value;
		}

		/**
		 * An option changed its value.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateOption(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] nameTmp = new byte[input.readInt()];
				input.readFully(nameTmp);
				this.name = new String(nameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case OptionValueBoolean.CONSTRUCTOR: this.value = new OptionValueBoolean(input); break;
					case OptionValueEmpty.CONSTRUCTOR: this.value = new OptionValueEmpty(input); break;
					case OptionValueInteger.CONSTRUCTOR: this.value = new OptionValueInteger(input); break;
					case OptionValueString.CONSTRUCTOR: this.value = new OptionValueString(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateOption.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateOption.CONSTRUCTOR);
			if (this.name == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nameTmp = this.name.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nameTmp.length);
				output.write(nameTmp);
			}
			if (this.value == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.value.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateOption updateOption = (UpdateOption) o;
			if (this.name != updateOption.name) {
				return false;
			}
			if (!Objects.equals(this.value, updateOption.value)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.name == null ? 0 : this.name.hashCode();
			result = result * 31 + (this.value == null ? 0 : this.value.hashCode());
			return result;
		}
	}

	/**
	 * A sticker set has changed.
	**/
	public static final class UpdateStickerSet extends Update {


		/**
		 * The sticker set.
		**/
		public StickerSet stickerSet;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1879268812;

		/**
		 * A sticker set has changed.
		**/
		public UpdateStickerSet() {}

		/**
		 * A sticker set has changed.
		 *
		 * @param stickerSet The sticker set.
		**/
		public UpdateStickerSet(StickerSet stickerSet) {
			this.stickerSet = stickerSet;
		}

		/**
		 * A sticker set has changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateStickerSet(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (StickerSet.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.stickerSet = new StickerSet(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateStickerSet.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateStickerSet.CONSTRUCTOR);
			if (this.stickerSet == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.stickerSet.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateStickerSet updateStickerSet = (UpdateStickerSet) o;
			if (!Objects.equals(this.stickerSet, updateStickerSet.stickerSet)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.stickerSet == null ? 0 : this.stickerSet.hashCode();
		}
	}

	/**
	 * The list of installed sticker sets was updated.
	**/
	public static final class UpdateInstalledStickerSets extends Update {


		/**
		 * Type of the affected stickers.
		**/
		public StickerType stickerType;

		/**
		 * The new list of installed ordinary sticker sets.
		**/
		public long[] stickerSetIds;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1735084182;

		/**
		 * The list of installed sticker sets was updated.
		**/
		public UpdateInstalledStickerSets() {}

		/**
		 * The list of installed sticker sets was updated.
		 *
		 * @param stickerType Type of the affected stickers.
		 * @param stickerSetIds The new list of installed ordinary sticker sets.
		**/
		public UpdateInstalledStickerSets(StickerType stickerType, long[] stickerSetIds) {
			this.stickerType = stickerType;
			this.stickerSetIds = stickerSetIds;
		}

		/**
		 * The list of installed sticker sets was updated.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateInstalledStickerSets(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case StickerTypeRegular.CONSTRUCTOR: this.stickerType = new StickerTypeRegular(input); break;
					case StickerTypeMask.CONSTRUCTOR: this.stickerType = new StickerTypeMask(input); break;
					case StickerTypeCustomEmoji.CONSTRUCTOR: this.stickerType = new StickerTypeCustomEmoji(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				this.stickerSetIds = new long[input.readInt()];
				for (int i = 0; i < this.stickerSetIds.length; i++) {
					this.stickerSetIds[i] = input.readLong();
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateInstalledStickerSets.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateInstalledStickerSets.CONSTRUCTOR);
			if (this.stickerType == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.stickerType.serialize(output);
			}
			if (this.stickerSetIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.stickerSetIds.length);
				for (int i = 0; i < this.stickerSetIds.length; i++) {
					output.writeLong(this.stickerSetIds[i]);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateInstalledStickerSets updateInstalledStickerSets = (UpdateInstalledStickerSets) o;
			if (!Objects.equals(this.stickerType, updateInstalledStickerSets.stickerType)) {
				return false;
			}
			if (!Arrays.equals(this.stickerSetIds, updateInstalledStickerSets.stickerSetIds)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.stickerType == null ? 0 : this.stickerType.hashCode();
			result = result * 31 + (Arrays.hashCode(this.stickerSetIds));
			return result;
		}
	}

	/**
	 * The list of trending sticker sets was updated or some of them were
	 * viewed.
	**/
	public static final class UpdateTrendingStickerSets extends Update {


		/**
		 * Type of the affected stickers.
		**/
		public StickerType stickerType;

		/**
		 * The prefix of the list of trending sticker sets with the newest trending sticker sets.
		**/
		public TrendingStickerSets stickerSets;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1266307239;

		/**
		 * The list of trending sticker sets was updated or some of them were viewed.
		**/
		public UpdateTrendingStickerSets() {}

		/**
		 * The list of trending sticker sets was updated or some of them were viewed.
		 *
		 * @param stickerType Type of the affected stickers.
		 * @param stickerSets The prefix of the list of trending sticker sets with the newest trending sticker sets.
		**/
		public UpdateTrendingStickerSets(StickerType stickerType, TrendingStickerSets stickerSets) {
			this.stickerType = stickerType;
			this.stickerSets = stickerSets;
		}

		/**
		 * The list of trending sticker sets was updated or some of them were viewed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateTrendingStickerSets(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case StickerTypeRegular.CONSTRUCTOR: this.stickerType = new StickerTypeRegular(input); break;
					case StickerTypeMask.CONSTRUCTOR: this.stickerType = new StickerTypeMask(input); break;
					case StickerTypeCustomEmoji.CONSTRUCTOR: this.stickerType = new StickerTypeCustomEmoji(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				if (TrendingStickerSets.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.stickerSets = new TrendingStickerSets(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateTrendingStickerSets.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateTrendingStickerSets.CONSTRUCTOR);
			if (this.stickerType == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.stickerType.serialize(output);
			}
			if (this.stickerSets == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.stickerSets.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateTrendingStickerSets updateTrendingStickerSets = (UpdateTrendingStickerSets) o;
			if (!Objects.equals(this.stickerType, updateTrendingStickerSets.stickerType)) {
				return false;
			}
			if (!Objects.equals(this.stickerSets, updateTrendingStickerSets.stickerSets)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.stickerType == null ? 0 : this.stickerType.hashCode();
			result = result * 31 + (this.stickerSets == null ? 0 : this.stickerSets.hashCode());
			return result;
		}
	}

	/**
	 * The list of recently used stickers was updated.
	**/
	public static final class UpdateRecentStickers extends Update {


		/**
		 * True, if the list of stickers attached to photo or video files was updated; otherwise, the list of sent stickers is updated.
		**/
		public boolean isAttached;

		/**
		 * The new list of file identifiers of recently used stickers.
		**/
		public int[] stickerIds;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1906403540;

		/**
		 * The list of recently used stickers was updated.
		**/
		public UpdateRecentStickers() {}

		/**
		 * The list of recently used stickers was updated.
		 *
		 * @param isAttached True, if the list of stickers attached to photo or video files was updated; otherwise, the list of sent stickers is updated.
		 * @param stickerIds The new list of file identifiers of recently used stickers.
		**/
		public UpdateRecentStickers(boolean isAttached, int[] stickerIds) {
			this.isAttached = isAttached;
			this.stickerIds = stickerIds;
		}

		/**
		 * The list of recently used stickers was updated.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateRecentStickers(DataInput input) throws IOException {
			this.isAttached = input.readBoolean();
			if (input.readBoolean()) {
				this.stickerIds = new int[input.readInt()];
				for (int i = 0; i < this.stickerIds.length; i++) {
					this.stickerIds[i] = input.readInt();
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateRecentStickers.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateRecentStickers.CONSTRUCTOR);
			output.writeBoolean(this.isAttached);
			if (this.stickerIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.stickerIds.length);
				for (int i = 0; i < this.stickerIds.length; i++) {
					output.writeInt(this.stickerIds[i]);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateRecentStickers updateRecentStickers = (UpdateRecentStickers) o;
			if (this.isAttached != updateRecentStickers.isAttached) {
				return false;
			}
			if (!Arrays.equals(this.stickerIds, updateRecentStickers.stickerIds)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isAttached);
			result = result * 31 + (Arrays.hashCode(this.stickerIds));
			return result;
		}
	}

	/**
	 * The list of favorite stickers was updated.
	**/
	public static final class UpdateFavoriteStickers extends Update {


		/**
		 * The new list of file identifiers of favorite stickers.
		**/
		public int[] stickerIds;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1662240999;

		/**
		 * The list of favorite stickers was updated.
		**/
		public UpdateFavoriteStickers() {}

		/**
		 * The list of favorite stickers was updated.
		 *
		 * @param stickerIds The new list of file identifiers of favorite stickers.
		**/
		public UpdateFavoriteStickers(int[] stickerIds) {
			this.stickerIds = stickerIds;
		}

		/**
		 * The list of favorite stickers was updated.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateFavoriteStickers(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.stickerIds = new int[input.readInt()];
				for (int i = 0; i < this.stickerIds.length; i++) {
					this.stickerIds[i] = input.readInt();
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateFavoriteStickers.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateFavoriteStickers.CONSTRUCTOR);
			if (this.stickerIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.stickerIds.length);
				for (int i = 0; i < this.stickerIds.length; i++) {
					output.writeInt(this.stickerIds[i]);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateFavoriteStickers updateFavoriteStickers = (UpdateFavoriteStickers) o;
			if (!Arrays.equals(this.stickerIds, updateFavoriteStickers.stickerIds)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.stickerIds);
		}
	}

	/**
	 * The list of saved animations was updated.
	**/
	public static final class UpdateSavedAnimations extends Update {


		/**
		 * The new list of file identifiers of saved animations.
		**/
		public int[] animationIds;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 65563814;

		/**
		 * The list of saved animations was updated.
		**/
		public UpdateSavedAnimations() {}

		/**
		 * The list of saved animations was updated.
		 *
		 * @param animationIds The new list of file identifiers of saved animations.
		**/
		public UpdateSavedAnimations(int[] animationIds) {
			this.animationIds = animationIds;
		}

		/**
		 * The list of saved animations was updated.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateSavedAnimations(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.animationIds = new int[input.readInt()];
				for (int i = 0; i < this.animationIds.length; i++) {
					this.animationIds[i] = input.readInt();
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateSavedAnimations.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateSavedAnimations.CONSTRUCTOR);
			if (this.animationIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.animationIds.length);
				for (int i = 0; i < this.animationIds.length; i++) {
					output.writeInt(this.animationIds[i]);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateSavedAnimations updateSavedAnimations = (UpdateSavedAnimations) o;
			if (!Arrays.equals(this.animationIds, updateSavedAnimations.animationIds)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.animationIds);
		}
	}

	/**
	 * The list of saved notifications sounds was updated. This update may
	 * not be sent until information about a notification sound was
	 * requested for the first time.
	**/
	public static final class UpdateSavedNotificationSounds extends Update {


		/**
		 * The new list of identifiers of saved notification sounds.
		**/
		public long[] notificationSoundIds;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1052725698;

		/**
		 * The list of saved notifications sounds was updated. This update may not be sent until information about a notification sound was requested for the first time.
		**/
		public UpdateSavedNotificationSounds() {}

		/**
		 * The list of saved notifications sounds was updated. This update may not be sent until information about a notification sound was requested for the first time.
		 *
		 * @param notificationSoundIds The new list of identifiers of saved notification sounds.
		**/
		public UpdateSavedNotificationSounds(long[] notificationSoundIds) {
			this.notificationSoundIds = notificationSoundIds;
		}

		/**
		 * The list of saved notifications sounds was updated. This update may not be sent until information about a notification sound was requested for the first time.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateSavedNotificationSounds(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.notificationSoundIds = new long[input.readInt()];
				for (int i = 0; i < this.notificationSoundIds.length; i++) {
					this.notificationSoundIds[i] = input.readLong();
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateSavedNotificationSounds.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateSavedNotificationSounds.CONSTRUCTOR);
			if (this.notificationSoundIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.notificationSoundIds.length);
				for (int i = 0; i < this.notificationSoundIds.length; i++) {
					output.writeLong(this.notificationSoundIds[i]);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateSavedNotificationSounds updateSavedNotificationSounds = (UpdateSavedNotificationSounds) o;
			if (!Arrays.equals(this.notificationSoundIds, updateSavedNotificationSounds.notificationSoundIds)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.notificationSoundIds);
		}
	}

	/**
	 * The selected background has changed.
	**/
	public static final class UpdateSelectedBackground extends Update {


		/**
		 * True, if background for dark theme has changed.
		**/
		public boolean forDarkTheme;

		/**
		 * The new selected background; may be null.
		**/
		public Background background;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1715658659;

		/**
		 * The selected background has changed.
		**/
		public UpdateSelectedBackground() {}

		/**
		 * The selected background has changed.
		 *
		 * @param forDarkTheme True, if background for dark theme has changed.
		 * @param background The new selected background; may be null.
		**/
		public UpdateSelectedBackground(boolean forDarkTheme, Background background) {
			this.forDarkTheme = forDarkTheme;
			this.background = background;
		}

		/**
		 * The selected background has changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateSelectedBackground(DataInput input) throws IOException {
			this.forDarkTheme = input.readBoolean();
			if (input.readBoolean()) {
				if (Background.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.background = new Background(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateSelectedBackground.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateSelectedBackground.CONSTRUCTOR);
			output.writeBoolean(this.forDarkTheme);
			if (this.background == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.background.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateSelectedBackground updateSelectedBackground = (UpdateSelectedBackground) o;
			if (this.forDarkTheme != updateSelectedBackground.forDarkTheme) {
				return false;
			}
			if (!Objects.equals(this.background, updateSelectedBackground.background)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.forDarkTheme);
			result = result * 31 + (this.background == null ? 0 : this.background.hashCode());
			return result;
		}
	}

	/**
	 * The list of available chat themes has changed.
	**/
	public static final class UpdateChatThemes extends Update {


		/**
		 * The new list of chat themes.
		**/
		public ChatTheme[] chatThemes;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1588098376;

		/**
		 * The list of available chat themes has changed.
		**/
		public UpdateChatThemes() {}

		/**
		 * The list of available chat themes has changed.
		 *
		 * @param chatThemes The new list of chat themes.
		**/
		public UpdateChatThemes(ChatTheme[] chatThemes) {
			this.chatThemes = chatThemes;
		}

		/**
		 * The list of available chat themes has changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateChatThemes(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.chatThemes = new ChatTheme[input.readInt()];
				for (int i = 0; i < this.chatThemes.length; i++) {
					if (ChatTheme.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.chatThemes[i] = new ChatTheme(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateChatThemes.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateChatThemes.CONSTRUCTOR);
			if (this.chatThemes == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.chatThemes.length);
				for (int i = 0; i < this.chatThemes.length; i++) {
					this.chatThemes[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateChatThemes updateChatThemes = (UpdateChatThemes) o;
			if (!Arrays.equals(this.chatThemes, updateChatThemes.chatThemes)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.chatThemes);
		}
	}

	/**
	 * Some language pack strings have been updated.
	**/
	public static final class UpdateLanguagePackStrings extends Update {


		/**
		 * Localization target to which the language pack belongs.
		**/
		public String localizationTarget;

		/**
		 * Identifier of the updated language pack.
		**/
		public String languagePackId;

		/**
		 * List of changed language pack strings; empty if all strings have changed.
		**/
		public LanguagePackString[] strings;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1056319886;

		/**
		 * Some language pack strings have been updated.
		**/
		public UpdateLanguagePackStrings() {}

		/**
		 * Some language pack strings have been updated.
		 *
		 * @param localizationTarget Localization target to which the language pack belongs.
		 * @param languagePackId Identifier of the updated language pack.
		 * @param strings List of changed language pack strings; empty if all strings have changed.
		**/
		public UpdateLanguagePackStrings(String localizationTarget,
				String languagePackId,
				LanguagePackString[] strings) {
			this.localizationTarget = localizationTarget;
			this.languagePackId = languagePackId;
			this.strings = strings;
		}

		/**
		 * Some language pack strings have been updated.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateLanguagePackStrings(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] localizationTargetTmp = new byte[input.readInt()];
				input.readFully(localizationTargetTmp);
				this.localizationTarget = new String(localizationTargetTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] languagePackIdTmp = new byte[input.readInt()];
				input.readFully(languagePackIdTmp);
				this.languagePackId = new String(languagePackIdTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				this.strings = new LanguagePackString[input.readInt()];
				for (int i = 0; i < this.strings.length; i++) {
					if (LanguagePackString.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.strings[i] = new LanguagePackString(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateLanguagePackStrings.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateLanguagePackStrings.CONSTRUCTOR);
			if (this.localizationTarget == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] localizationTargetTmp = this.localizationTarget.getBytes(StandardCharsets.UTF_8);
				output.writeInt(localizationTargetTmp.length);
				output.write(localizationTargetTmp);
			}
			if (this.languagePackId == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] languagePackIdTmp = this.languagePackId.getBytes(StandardCharsets.UTF_8);
				output.writeInt(languagePackIdTmp.length);
				output.write(languagePackIdTmp);
			}
			if (this.strings == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.strings.length);
				for (int i = 0; i < this.strings.length; i++) {
					this.strings[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateLanguagePackStrings updateLanguagePackStrings = (UpdateLanguagePackStrings) o;
			if (this.localizationTarget != updateLanguagePackStrings.localizationTarget) {
				return false;
			}
			if (this.languagePackId != updateLanguagePackStrings.languagePackId) {
				return false;
			}
			if (!Arrays.equals(this.strings, updateLanguagePackStrings.strings)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.localizationTarget == null ? 0 : this.localizationTarget.hashCode();
			result = result * 31 + (this.languagePackId == null ? 0 : this.languagePackId.hashCode());
			result = result * 31 + (Arrays.hashCode(this.strings));
			return result;
		}
	}

	/**
	 * The connection state has changed. This update must be used only to
	 * show a human-readable description of the connection state.
	**/
	public static final class UpdateConnectionState extends Update {


		/**
		 * The new connection state.
		**/
		public ConnectionState state;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1469292078;

		/**
		 * The connection state has changed. This update must be used only to show a human-readable description of the connection state.
		**/
		public UpdateConnectionState() {}

		/**
		 * The connection state has changed. This update must be used only to show a human-readable description of the connection state.
		 *
		 * @param state The new connection state.
		**/
		public UpdateConnectionState(ConnectionState state) {
			this.state = state;
		}

		/**
		 * The connection state has changed. This update must be used only to show a human-readable description of the connection state.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateConnectionState(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ConnectionStateWaitingForNetwork.CONSTRUCTOR: this.state = new ConnectionStateWaitingForNetwork(input); break;
					case ConnectionStateConnectingToProxy.CONSTRUCTOR: this.state = new ConnectionStateConnectingToProxy(input); break;
					case ConnectionStateConnecting.CONSTRUCTOR: this.state = new ConnectionStateConnecting(input); break;
					case ConnectionStateUpdating.CONSTRUCTOR: this.state = new ConnectionStateUpdating(input); break;
					case ConnectionStateReady.CONSTRUCTOR: this.state = new ConnectionStateReady(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateConnectionState.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateConnectionState.CONSTRUCTOR);
			if (this.state == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.state.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateConnectionState updateConnectionState = (UpdateConnectionState) o;
			if (!Objects.equals(this.state, updateConnectionState.state)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.state == null ? 0 : this.state.hashCode();
		}
	}

	/**
	 * New terms of service must be accepted by the user. If the terms of
	 * service are declined, then the deleteAccount method must be called
	 * with the reason &quot;Decline ToS update&quot;.
	**/
	public static final class UpdateTermsOfService extends Update {


		/**
		 * Identifier of the terms of service.
		**/
		public String termsOfServiceId;

		/**
		 * The new terms of service.
		**/
		public TermsOfService termsOfService;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1304640162;

		/**
		 * New terms of service must be accepted by the user. If the terms of service are declined, then the deleteAccount method must be called with the reason &quot;Decline ToS update&quot;.
		**/
		public UpdateTermsOfService() {}

		/**
		 * New terms of service must be accepted by the user. If the terms of service are declined, then the deleteAccount method must be called with the reason &quot;Decline ToS update&quot;.
		 *
		 * @param termsOfServiceId Identifier of the terms of service.
		 * @param termsOfService The new terms of service.
		**/
		public UpdateTermsOfService(String termsOfServiceId, TermsOfService termsOfService) {
			this.termsOfServiceId = termsOfServiceId;
			this.termsOfService = termsOfService;
		}

		/**
		 * New terms of service must be accepted by the user. If the terms of service are declined, then the deleteAccount method must be called with the reason &quot;Decline ToS update&quot;.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateTermsOfService(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] termsOfServiceIdTmp = new byte[input.readInt()];
				input.readFully(termsOfServiceIdTmp);
				this.termsOfServiceId = new String(termsOfServiceIdTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (TermsOfService.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.termsOfService = new TermsOfService(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateTermsOfService.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateTermsOfService.CONSTRUCTOR);
			if (this.termsOfServiceId == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] termsOfServiceIdTmp = this.termsOfServiceId.getBytes(StandardCharsets.UTF_8);
				output.writeInt(termsOfServiceIdTmp.length);
				output.write(termsOfServiceIdTmp);
			}
			if (this.termsOfService == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.termsOfService.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateTermsOfService updateTermsOfService = (UpdateTermsOfService) o;
			if (this.termsOfServiceId != updateTermsOfService.termsOfServiceId) {
				return false;
			}
			if (!Objects.equals(this.termsOfService, updateTermsOfService.termsOfService)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.termsOfServiceId == null ? 0 : this.termsOfServiceId.hashCode();
			result = result * 31 + (this.termsOfService == null ? 0 : this.termsOfService.hashCode());
			return result;
		}
	}

	/**
	 * The list of users nearby has changed. The update is guaranteed to be
	 * sent only 60 seconds after a successful searchChatsNearby request.
	**/
	public static final class UpdateUsersNearby extends Update {


		/**
		 * The new list of users nearby.
		**/
		public ChatNearby[] usersNearby;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1517109163;

		/**
		 * The list of users nearby has changed. The update is guaranteed to be sent only 60 seconds after a successful searchChatsNearby request.
		**/
		public UpdateUsersNearby() {}

		/**
		 * The list of users nearby has changed. The update is guaranteed to be sent only 60 seconds after a successful searchChatsNearby request.
		 *
		 * @param usersNearby The new list of users nearby.
		**/
		public UpdateUsersNearby(ChatNearby[] usersNearby) {
			this.usersNearby = usersNearby;
		}

		/**
		 * The list of users nearby has changed. The update is guaranteed to be sent only 60 seconds after a successful searchChatsNearby request.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateUsersNearby(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.usersNearby = new ChatNearby[input.readInt()];
				for (int i = 0; i < this.usersNearby.length; i++) {
					if (ChatNearby.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.usersNearby[i] = new ChatNearby(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateUsersNearby.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateUsersNearby.CONSTRUCTOR);
			if (this.usersNearby == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.usersNearby.length);
				for (int i = 0; i < this.usersNearby.length; i++) {
					this.usersNearby[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateUsersNearby updateUsersNearby = (UpdateUsersNearby) o;
			if (!Arrays.equals(this.usersNearby, updateUsersNearby.usersNearby)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.usersNearby);
		}
	}

	/**
	 * The list of bots added to attachment menu has changed.
	**/
	public static final class UpdateAttachmentMenuBots extends Update {


		/**
		 * The new list of bots added to attachment menu. The bots must not be shown on scheduled messages screen.
		**/
		public AttachmentMenuBot[] bots;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 291369922;

		/**
		 * The list of bots added to attachment menu has changed.
		**/
		public UpdateAttachmentMenuBots() {}

		/**
		 * The list of bots added to attachment menu has changed.
		 *
		 * @param bots The new list of bots added to attachment menu. The bots must not be shown on scheduled messages screen.
		**/
		public UpdateAttachmentMenuBots(AttachmentMenuBot[] bots) {
			this.bots = bots;
		}

		/**
		 * The list of bots added to attachment menu has changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateAttachmentMenuBots(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.bots = new AttachmentMenuBot[input.readInt()];
				for (int i = 0; i < this.bots.length; i++) {
					if (AttachmentMenuBot.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.bots[i] = new AttachmentMenuBot(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateAttachmentMenuBots.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateAttachmentMenuBots.CONSTRUCTOR);
			if (this.bots == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.bots.length);
				for (int i = 0; i < this.bots.length; i++) {
					this.bots[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateAttachmentMenuBots updateAttachmentMenuBots = (UpdateAttachmentMenuBots) o;
			if (!Arrays.equals(this.bots, updateAttachmentMenuBots.bots)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.bots);
		}
	}

	/**
	 * A message was sent by an opened Web App, so the Web App needs to be
	 * closed.
	**/
	public static final class UpdateWebAppMessageSent extends Update {


		/**
		 * Identifier of Web App launch.
		**/
		public long webAppLaunchId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1480790569;

		/**
		 * A message was sent by an opened Web App, so the Web App needs to be closed.
		**/
		public UpdateWebAppMessageSent() {}

		/**
		 * A message was sent by an opened Web App, so the Web App needs to be closed.
		 *
		 * @param webAppLaunchId Identifier of Web App launch.
		**/
		public UpdateWebAppMessageSent(long webAppLaunchId) {
			this.webAppLaunchId = webAppLaunchId;
		}

		/**
		 * A message was sent by an opened Web App, so the Web App needs to be closed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateWebAppMessageSent(DataInput input) throws IOException {
			this.webAppLaunchId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateWebAppMessageSent.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateWebAppMessageSent.CONSTRUCTOR);
			output.writeLong(this.webAppLaunchId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateWebAppMessageSent updateWebAppMessageSent = (UpdateWebAppMessageSent) o;
			if (this.webAppLaunchId != updateWebAppMessageSent.webAppLaunchId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.webAppLaunchId);
		}
	}

	/**
	 * The list of active emoji reactions has changed.
	**/
	public static final class UpdateActiveEmojiReactions extends Update {


		/**
		 * The new list of active emoji reactions.
		**/
		public String[] emojis;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 77556818;

		/**
		 * The list of active emoji reactions has changed.
		**/
		public UpdateActiveEmojiReactions() {}

		/**
		 * The list of active emoji reactions has changed.
		 *
		 * @param emojis The new list of active emoji reactions.
		**/
		public UpdateActiveEmojiReactions(String[] emojis) {
			this.emojis = emojis;
		}

		/**
		 * The list of active emoji reactions has changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateActiveEmojiReactions(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.emojis = new String[input.readInt()];
				for (int i = 0; i < this.emojis.length; i++) {
					byte[] emojisTmp = new byte[input.readInt()];
					input.readFully(emojisTmp);
					this.emojis[i] = new String(emojisTmp, StandardCharsets.UTF_8);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateActiveEmojiReactions.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateActiveEmojiReactions.CONSTRUCTOR);
			if (this.emojis == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.emojis.length);
				for (int i = 0; i < this.emojis.length; i++) {
					byte[] emojisTmp = this.emojis[i].getBytes(StandardCharsets.UTF_8);
					output.writeInt(emojisTmp.length);
					output.write(emojisTmp);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateActiveEmojiReactions updateActiveEmojiReactions = (UpdateActiveEmojiReactions) o;
			if (!Arrays.equals(this.emojis, updateActiveEmojiReactions.emojis)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.emojis);
		}
	}

	/**
	 * The type of default reaction has changed.
	**/
	public static final class UpdateDefaultReactionType extends Update {


		/**
		 * The new type of the default reaction.
		**/
		public ReactionType reactionType;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1264668933;

		/**
		 * The type of default reaction has changed.
		**/
		public UpdateDefaultReactionType() {}

		/**
		 * The type of default reaction has changed.
		 *
		 * @param reactionType The new type of the default reaction.
		**/
		public UpdateDefaultReactionType(ReactionType reactionType) {
			this.reactionType = reactionType;
		}

		/**
		 * The type of default reaction has changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateDefaultReactionType(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ReactionTypeEmoji.CONSTRUCTOR: this.reactionType = new ReactionTypeEmoji(input); break;
					case ReactionTypeCustomEmoji.CONSTRUCTOR: this.reactionType = new ReactionTypeCustomEmoji(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateDefaultReactionType.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateDefaultReactionType.CONSTRUCTOR);
			if (this.reactionType == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.reactionType.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateDefaultReactionType updateDefaultReactionType = (UpdateDefaultReactionType) o;
			if (!Objects.equals(this.reactionType, updateDefaultReactionType.reactionType)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.reactionType == null ? 0 : this.reactionType.hashCode();
		}
	}

	/**
	 * The list of supported dice emojis has changed.
	**/
	public static final class UpdateDiceEmojis extends Update {


		/**
		 * The new list of supported dice emojis.
		**/
		public String[] emojis;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1069066940;

		/**
		 * The list of supported dice emojis has changed.
		**/
		public UpdateDiceEmojis() {}

		/**
		 * The list of supported dice emojis has changed.
		 *
		 * @param emojis The new list of supported dice emojis.
		**/
		public UpdateDiceEmojis(String[] emojis) {
			this.emojis = emojis;
		}

		/**
		 * The list of supported dice emojis has changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateDiceEmojis(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.emojis = new String[input.readInt()];
				for (int i = 0; i < this.emojis.length; i++) {
					byte[] emojisTmp = new byte[input.readInt()];
					input.readFully(emojisTmp);
					this.emojis[i] = new String(emojisTmp, StandardCharsets.UTF_8);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateDiceEmojis.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateDiceEmojis.CONSTRUCTOR);
			if (this.emojis == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.emojis.length);
				for (int i = 0; i < this.emojis.length; i++) {
					byte[] emojisTmp = this.emojis[i].getBytes(StandardCharsets.UTF_8);
					output.writeInt(emojisTmp.length);
					output.write(emojisTmp);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateDiceEmojis updateDiceEmojis = (UpdateDiceEmojis) o;
			if (!Arrays.equals(this.emojis, updateDiceEmojis.emojis)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.emojis);
		}
	}

	/**
	 * Some animated emoji message was clicked and a big animated sticker
	 * must be played if the message is visible on the screen.
	 * chatActionWatchingAnimations with the text of the message needs to be
	 * sent if the sticker is played.
	**/
	public static final class UpdateAnimatedEmojiMessageClicked extends Update {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Message identifier.
		**/
		public long messageId;

		/**
		 * The animated sticker to be played.
		**/
		public Sticker sticker;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1558809595;

		/**
		 * Some animated emoji message was clicked and a big animated sticker must be played if the message is visible on the screen. chatActionWatchingAnimations with the text of the message needs to be sent if the sticker is played.
		**/
		public UpdateAnimatedEmojiMessageClicked() {}

		/**
		 * Some animated emoji message was clicked and a big animated sticker must be played if the message is visible on the screen. chatActionWatchingAnimations with the text of the message needs to be sent if the sticker is played.
		 *
		 * @param chatId Chat identifier.
		 * @param messageId Message identifier.
		 * @param sticker The animated sticker to be played.
		**/
		public UpdateAnimatedEmojiMessageClicked(long chatId, long messageId, Sticker sticker) {
			this.chatId = chatId;
			this.messageId = messageId;
			this.sticker = sticker;
		}

		/**
		 * Some animated emoji message was clicked and a big animated sticker must be played if the message is visible on the screen. chatActionWatchingAnimations with the text of the message needs to be sent if the sticker is played.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateAnimatedEmojiMessageClicked(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
			if (input.readBoolean()) {
				if (Sticker.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.sticker = new Sticker(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateAnimatedEmojiMessageClicked.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateAnimatedEmojiMessageClicked.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
			if (this.sticker == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.sticker.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateAnimatedEmojiMessageClicked updateAnimatedEmojiMessageClicked = (UpdateAnimatedEmojiMessageClicked) o;
			if (this.chatId != updateAnimatedEmojiMessageClicked.chatId) {
				return false;
			}
			if (this.messageId != updateAnimatedEmojiMessageClicked.messageId) {
				return false;
			}
			if (!Objects.equals(this.sticker, updateAnimatedEmojiMessageClicked.sticker)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.sticker == null ? 0 : this.sticker.hashCode());
			return result;
		}
	}

	/**
	 * The parameters of animation search through
	 * getOption(&quot;animation_search_bot_username&quot;) bot has changed.
	**/
	public static final class UpdateAnimationSearchParameters extends Update {


		/**
		 * Name of the animation search provider.
		**/
		public String provider;

		/**
		 * The new list of emojis suggested for searching.
		**/
		public String[] emojis;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1144983202;

		/**
		 * The parameters of animation search through getOption(&quot;animation_search_bot_username&quot;) bot has changed.
		**/
		public UpdateAnimationSearchParameters() {}

		/**
		 * The parameters of animation search through getOption(&quot;animation_search_bot_username&quot;) bot has changed.
		 *
		 * @param provider Name of the animation search provider.
		 * @param emojis The new list of emojis suggested for searching.
		**/
		public UpdateAnimationSearchParameters(String provider, String[] emojis) {
			this.provider = provider;
			this.emojis = emojis;
		}

		/**
		 * The parameters of animation search through getOption(&quot;animation_search_bot_username&quot;) bot has changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateAnimationSearchParameters(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] providerTmp = new byte[input.readInt()];
				input.readFully(providerTmp);
				this.provider = new String(providerTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				this.emojis = new String[input.readInt()];
				for (int i = 0; i < this.emojis.length; i++) {
					byte[] emojisTmp = new byte[input.readInt()];
					input.readFully(emojisTmp);
					this.emojis[i] = new String(emojisTmp, StandardCharsets.UTF_8);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateAnimationSearchParameters.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateAnimationSearchParameters.CONSTRUCTOR);
			if (this.provider == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] providerTmp = this.provider.getBytes(StandardCharsets.UTF_8);
				output.writeInt(providerTmp.length);
				output.write(providerTmp);
			}
			if (this.emojis == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.emojis.length);
				for (int i = 0; i < this.emojis.length; i++) {
					byte[] emojisTmp = this.emojis[i].getBytes(StandardCharsets.UTF_8);
					output.writeInt(emojisTmp.length);
					output.write(emojisTmp);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateAnimationSearchParameters updateAnimationSearchParameters = (UpdateAnimationSearchParameters) o;
			if (this.provider != updateAnimationSearchParameters.provider) {
				return false;
			}
			if (!Arrays.equals(this.emojis, updateAnimationSearchParameters.emojis)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.provider == null ? 0 : this.provider.hashCode();
			result = result * 31 + (Arrays.hashCode(this.emojis));
			return result;
		}
	}

	/**
	 * The list of suggested to the user actions has changed.
	**/
	public static final class UpdateSuggestedActions extends Update {


		/**
		 * Added suggested actions.
		**/
		public SuggestedAction[] addedActions;

		/**
		 * Removed suggested actions.
		**/
		public SuggestedAction[] removedActions;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1459452346;

		/**
		 * The list of suggested to the user actions has changed.
		**/
		public UpdateSuggestedActions() {}

		/**
		 * The list of suggested to the user actions has changed.
		 *
		 * @param addedActions Added suggested actions.
		 * @param removedActions Removed suggested actions.
		**/
		public UpdateSuggestedActions(SuggestedAction[] addedActions,
				SuggestedAction[] removedActions) {
			this.addedActions = addedActions;
			this.removedActions = removedActions;
		}

		/**
		 * The list of suggested to the user actions has changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateSuggestedActions(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.addedActions = new SuggestedAction[input.readInt()];
				for (int i = 0; i < this.addedActions.length; i++) {
					switch(input.readInt()) {
						case SuggestedActionEnableArchiveAndMuteNewChats.CONSTRUCTOR: this.addedActions[i] = new SuggestedActionEnableArchiveAndMuteNewChats(input); break;
						case SuggestedActionCheckPassword.CONSTRUCTOR: this.addedActions[i] = new SuggestedActionCheckPassword(input); break;
						case SuggestedActionCheckPhoneNumber.CONSTRUCTOR: this.addedActions[i] = new SuggestedActionCheckPhoneNumber(input); break;
						case SuggestedActionViewChecksHint.CONSTRUCTOR: this.addedActions[i] = new SuggestedActionViewChecksHint(input); break;
						case SuggestedActionConvertToBroadcastGroup.CONSTRUCTOR: this.addedActions[i] = new SuggestedActionConvertToBroadcastGroup(input); break;
						case SuggestedActionSetPassword.CONSTRUCTOR: this.addedActions[i] = new SuggestedActionSetPassword(input); break;
						case SuggestedActionUpgradePremium.CONSTRUCTOR: this.addedActions[i] = new SuggestedActionUpgradePremium(input); break;
						case SuggestedActionSubscribeToAnnualPremium.CONSTRUCTOR: this.addedActions[i] = new SuggestedActionSubscribeToAnnualPremium(input); break;
						default: {
							throw new UnsupportedOperationException();
						}
					}
				}
			}
			if (input.readBoolean()) {
				this.removedActions = new SuggestedAction[input.readInt()];
				for (int i = 0; i < this.removedActions.length; i++) {
					switch(input.readInt()) {
						case SuggestedActionEnableArchiveAndMuteNewChats.CONSTRUCTOR: this.removedActions[i] = new SuggestedActionEnableArchiveAndMuteNewChats(input); break;
						case SuggestedActionCheckPassword.CONSTRUCTOR: this.removedActions[i] = new SuggestedActionCheckPassword(input); break;
						case SuggestedActionCheckPhoneNumber.CONSTRUCTOR: this.removedActions[i] = new SuggestedActionCheckPhoneNumber(input); break;
						case SuggestedActionViewChecksHint.CONSTRUCTOR: this.removedActions[i] = new SuggestedActionViewChecksHint(input); break;
						case SuggestedActionConvertToBroadcastGroup.CONSTRUCTOR: this.removedActions[i] = new SuggestedActionConvertToBroadcastGroup(input); break;
						case SuggestedActionSetPassword.CONSTRUCTOR: this.removedActions[i] = new SuggestedActionSetPassword(input); break;
						case SuggestedActionUpgradePremium.CONSTRUCTOR: this.removedActions[i] = new SuggestedActionUpgradePremium(input); break;
						case SuggestedActionSubscribeToAnnualPremium.CONSTRUCTOR: this.removedActions[i] = new SuggestedActionSubscribeToAnnualPremium(input); break;
						default: {
							throw new UnsupportedOperationException();
						}
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateSuggestedActions.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateSuggestedActions.CONSTRUCTOR);
			if (this.addedActions == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.addedActions.length);
				for (int i = 0; i < this.addedActions.length; i++) {
					this.addedActions[i].serialize(output);
				}
			}
			if (this.removedActions == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.removedActions.length);
				for (int i = 0; i < this.removedActions.length; i++) {
					this.removedActions[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateSuggestedActions updateSuggestedActions = (UpdateSuggestedActions) o;
			if (!Arrays.equals(this.addedActions, updateSuggestedActions.addedActions)) {
				return false;
			}
			if (!Arrays.equals(this.removedActions, updateSuggestedActions.removedActions)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Arrays.hashCode(this.addedActions);
			result = result * 31 + (Arrays.hashCode(this.removedActions));
			return result;
		}
	}

	/**
	 * Adding users to a chat has failed because of their privacy settings.
	 * An invite link can be shared with the users if appropriate.
	**/
	public static final class UpdateAddChatMembersPrivacyForbidden extends Update {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Identifiers of users, which weren&#039;t added because of their privacy settings.
		**/
		public long[] userIds;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1435865611;

		/**
		 * Adding users to a chat has failed because of their privacy settings. An invite link can be shared with the users if appropriate.
		**/
		public UpdateAddChatMembersPrivacyForbidden() {}

		/**
		 * Adding users to a chat has failed because of their privacy settings. An invite link can be shared with the users if appropriate.
		 *
		 * @param chatId Chat identifier.
		 * @param userIds Identifiers of users, which weren&#039;t added because of their privacy settings.
		**/
		public UpdateAddChatMembersPrivacyForbidden(long chatId, long[] userIds) {
			this.chatId = chatId;
			this.userIds = userIds;
		}

		/**
		 * Adding users to a chat has failed because of their privacy settings. An invite link can be shared with the users if appropriate.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateAddChatMembersPrivacyForbidden(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				this.userIds = new long[input.readInt()];
				for (int i = 0; i < this.userIds.length; i++) {
					this.userIds[i] = input.readLong();
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateAddChatMembersPrivacyForbidden.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateAddChatMembersPrivacyForbidden.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.userIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.userIds.length);
				for (int i = 0; i < this.userIds.length; i++) {
					output.writeLong(this.userIds[i]);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateAddChatMembersPrivacyForbidden updateAddChatMembersPrivacyForbidden = (UpdateAddChatMembersPrivacyForbidden) o;
			if (this.chatId != updateAddChatMembersPrivacyForbidden.chatId) {
				return false;
			}
			if (!Arrays.equals(this.userIds, updateAddChatMembersPrivacyForbidden.userIds)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (Arrays.hashCode(this.userIds));
			return result;
		}
	}

	/**
	 * Autosave settings for some type of chats were updated.
	**/
	public static final class UpdateAutosaveSettings extends Update {


		/**
		 * Type of chats for which autosave settings were updated.
		**/
		public AutosaveSettingsScope scope;

		/**
		 * The new autosave settings; may be null if the settings are reset to default.
		**/
		public ScopeAutosaveSettings settings;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -634958069;

		/**
		 * Autosave settings for some type of chats were updated.
		**/
		public UpdateAutosaveSettings() {}

		/**
		 * Autosave settings for some type of chats were updated.
		 *
		 * @param scope Type of chats for which autosave settings were updated.
		 * @param settings The new autosave settings; may be null if the settings are reset to default.
		**/
		public UpdateAutosaveSettings(AutosaveSettingsScope scope, ScopeAutosaveSettings settings) {
			this.scope = scope;
			this.settings = settings;
		}

		/**
		 * Autosave settings for some type of chats were updated.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateAutosaveSettings(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case AutosaveSettingsScopePrivateChats.CONSTRUCTOR: this.scope = new AutosaveSettingsScopePrivateChats(input); break;
					case AutosaveSettingsScopeGroupChats.CONSTRUCTOR: this.scope = new AutosaveSettingsScopeGroupChats(input); break;
					case AutosaveSettingsScopeChannelChats.CONSTRUCTOR: this.scope = new AutosaveSettingsScopeChannelChats(input); break;
					case AutosaveSettingsScopeChat.CONSTRUCTOR: this.scope = new AutosaveSettingsScopeChat(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				if (ScopeAutosaveSettings.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.settings = new ScopeAutosaveSettings(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateAutosaveSettings.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateAutosaveSettings.CONSTRUCTOR);
			if (this.scope == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.scope.serialize(output);
			}
			if (this.settings == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.settings.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateAutosaveSettings updateAutosaveSettings = (UpdateAutosaveSettings) o;
			if (!Objects.equals(this.scope, updateAutosaveSettings.scope)) {
				return false;
			}
			if (!Objects.equals(this.settings, updateAutosaveSettings.settings)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.scope == null ? 0 : this.scope.hashCode();
			result = result * 31 + (this.settings == null ? 0 : this.settings.hashCode());
			return result;
		}
	}

	/**
	 * A new incoming inline query; for bots only.
	**/
	public static final class UpdateNewInlineQuery extends Update {


		/**
		 * Unique query identifier.
		**/
		public long id;

		/**
		 * Identifier of the user who sent the query.
		**/
		public long senderUserId;

		/**
		 * User location; may be null.
		**/
		public Location userLocation;

		/**
		 * The type of the chat from which the query originated; may be null if unknown.
		**/
		public ChatType chatType;

		/**
		 * Text of the query.
		**/
		public String query;

		/**
		 * Offset of the first entry to return.
		**/
		public String offset;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1903279924;

		/**
		 * A new incoming inline query; for bots only.
		**/
		public UpdateNewInlineQuery() {}

		/**
		 * A new incoming inline query; for bots only.
		 *
		 * @param id Unique query identifier.
		 * @param senderUserId Identifier of the user who sent the query.
		 * @param userLocation User location; may be null.
		 * @param chatType The type of the chat from which the query originated; may be null if unknown.
		 * @param query Text of the query.
		 * @param offset Offset of the first entry to return.
		**/
		public UpdateNewInlineQuery(long id,
				long senderUserId,
				Location userLocation,
				ChatType chatType,
				String query,
				String offset) {
			this.id = id;
			this.senderUserId = senderUserId;
			this.userLocation = userLocation;
			this.chatType = chatType;
			this.query = query;
			this.offset = offset;
		}

		/**
		 * A new incoming inline query; for bots only.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateNewInlineQuery(DataInput input) throws IOException {
			this.id = input.readLong();
			this.senderUserId = input.readLong();
			if (input.readBoolean()) {
				if (Location.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.userLocation = new Location(input);
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ChatTypePrivate.CONSTRUCTOR: this.chatType = new ChatTypePrivate(input); break;
					case ChatTypeBasicGroup.CONSTRUCTOR: this.chatType = new ChatTypeBasicGroup(input); break;
					case ChatTypeSupergroup.CONSTRUCTOR: this.chatType = new ChatTypeSupergroup(input); break;
					case ChatTypeSecret.CONSTRUCTOR: this.chatType = new ChatTypeSecret(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				byte[] queryTmp = new byte[input.readInt()];
				input.readFully(queryTmp);
				this.query = new String(queryTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] offsetTmp = new byte[input.readInt()];
				input.readFully(offsetTmp);
				this.offset = new String(offsetTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateNewInlineQuery.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateNewInlineQuery.CONSTRUCTOR);
			output.writeLong(this.id);
			output.writeLong(this.senderUserId);
			if (this.userLocation == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.userLocation.serialize(output);
			}
			if (this.chatType == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.chatType.serialize(output);
			}
			if (this.query == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] queryTmp = this.query.getBytes(StandardCharsets.UTF_8);
				output.writeInt(queryTmp.length);
				output.write(queryTmp);
			}
			if (this.offset == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] offsetTmp = this.offset.getBytes(StandardCharsets.UTF_8);
				output.writeInt(offsetTmp.length);
				output.write(offsetTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateNewInlineQuery updateNewInlineQuery = (UpdateNewInlineQuery) o;
			if (this.id != updateNewInlineQuery.id) {
				return false;
			}
			if (this.senderUserId != updateNewInlineQuery.senderUserId) {
				return false;
			}
			if (!Objects.equals(this.userLocation, updateNewInlineQuery.userLocation)) {
				return false;
			}
			if (!Objects.equals(this.chatType, updateNewInlineQuery.chatType)) {
				return false;
			}
			if (this.query != updateNewInlineQuery.query) {
				return false;
			}
			if (this.offset != updateNewInlineQuery.offset) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.id);
			result = result * 31 + (this.userLocation == null ? 0 : this.userLocation.hashCode());
			result = result * 31 + (this.chatType == null ? 0 : this.chatType.hashCode());
			result = result * 31 + (this.query == null ? 0 : this.query.hashCode());
			result = result * 31 + (this.offset == null ? 0 : this.offset.hashCode());
			return result;
		}
	}

	/**
	 * The user has chosen a result of an inline query; for bots only.
	**/
	public static final class UpdateNewChosenInlineResult extends Update {


		/**
		 * Identifier of the user who sent the query.
		**/
		public long senderUserId;

		/**
		 * User location; may be null.
		**/
		public Location userLocation;

		/**
		 * Text of the query.
		**/
		public String query;

		/**
		 * Identifier of the chosen result.
		**/
		public String resultId;

		/**
		 * Identifier of the sent inline message, if known.
		**/
		public String inlineMessageId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -884191395;

		/**
		 * The user has chosen a result of an inline query; for bots only.
		**/
		public UpdateNewChosenInlineResult() {}

		/**
		 * The user has chosen a result of an inline query; for bots only.
		 *
		 * @param senderUserId Identifier of the user who sent the query.
		 * @param userLocation User location; may be null.
		 * @param query Text of the query.
		 * @param resultId Identifier of the chosen result.
		 * @param inlineMessageId Identifier of the sent inline message, if known.
		**/
		public UpdateNewChosenInlineResult(long senderUserId,
				Location userLocation,
				String query,
				String resultId,
				String inlineMessageId) {
			this.senderUserId = senderUserId;
			this.userLocation = userLocation;
			this.query = query;
			this.resultId = resultId;
			this.inlineMessageId = inlineMessageId;
		}

		/**
		 * The user has chosen a result of an inline query; for bots only.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateNewChosenInlineResult(DataInput input) throws IOException {
			this.senderUserId = input.readLong();
			if (input.readBoolean()) {
				if (Location.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.userLocation = new Location(input);
			}
			if (input.readBoolean()) {
				byte[] queryTmp = new byte[input.readInt()];
				input.readFully(queryTmp);
				this.query = new String(queryTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] resultIdTmp = new byte[input.readInt()];
				input.readFully(resultIdTmp);
				this.resultId = new String(resultIdTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] inlineMessageIdTmp = new byte[input.readInt()];
				input.readFully(inlineMessageIdTmp);
				this.inlineMessageId = new String(inlineMessageIdTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateNewChosenInlineResult.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateNewChosenInlineResult.CONSTRUCTOR);
			output.writeLong(this.senderUserId);
			if (this.userLocation == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.userLocation.serialize(output);
			}
			if (this.query == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] queryTmp = this.query.getBytes(StandardCharsets.UTF_8);
				output.writeInt(queryTmp.length);
				output.write(queryTmp);
			}
			if (this.resultId == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] resultIdTmp = this.resultId.getBytes(StandardCharsets.UTF_8);
				output.writeInt(resultIdTmp.length);
				output.write(resultIdTmp);
			}
			if (this.inlineMessageId == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] inlineMessageIdTmp = this.inlineMessageId.getBytes(StandardCharsets.UTF_8);
				output.writeInt(inlineMessageIdTmp.length);
				output.write(inlineMessageIdTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateNewChosenInlineResult updateNewChosenInlineResult = (UpdateNewChosenInlineResult) o;
			if (this.senderUserId != updateNewChosenInlineResult.senderUserId) {
				return false;
			}
			if (!Objects.equals(this.userLocation, updateNewChosenInlineResult.userLocation)) {
				return false;
			}
			if (this.query != updateNewChosenInlineResult.query) {
				return false;
			}
			if (this.resultId != updateNewChosenInlineResult.resultId) {
				return false;
			}
			if (this.inlineMessageId != updateNewChosenInlineResult.inlineMessageId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.senderUserId);
			result = result * 31 + (this.userLocation == null ? 0 : this.userLocation.hashCode());
			result = result * 31 + (this.query == null ? 0 : this.query.hashCode());
			result = result * 31 + (this.resultId == null ? 0 : this.resultId.hashCode());
			result = result * 31 + (this.inlineMessageId == null ? 0 : this.inlineMessageId.hashCode());
			return result;
		}
	}

	/**
	 * A new incoming callback query; for bots only.
	**/
	public static final class UpdateNewCallbackQuery extends Update {


		/**
		 * Unique query identifier.
		**/
		public long id;

		/**
		 * Identifier of the user who sent the query.
		**/
		public long senderUserId;

		/**
		 * Identifier of the chat where the query was sent.
		**/
		public long chatId;

		/**
		 * Identifier of the message from which the query originated.
		**/
		public long messageId;

		/**
		 * Identifier that uniquely corresponds to the chat to which the message was sent.
		**/
		public long chatInstance;

		/**
		 * Query payload.
		**/
		public CallbackQueryPayload payload;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1989881762;

		/**
		 * A new incoming callback query; for bots only.
		**/
		public UpdateNewCallbackQuery() {}

		/**
		 * A new incoming callback query; for bots only.
		 *
		 * @param id Unique query identifier.
		 * @param senderUserId Identifier of the user who sent the query.
		 * @param chatId Identifier of the chat where the query was sent.
		 * @param messageId Identifier of the message from which the query originated.
		 * @param chatInstance Identifier that uniquely corresponds to the chat to which the message was sent.
		 * @param payload Query payload.
		**/
		public UpdateNewCallbackQuery(long id,
				long senderUserId,
				long chatId,
				long messageId,
				long chatInstance,
				CallbackQueryPayload payload) {
			this.id = id;
			this.senderUserId = senderUserId;
			this.chatId = chatId;
			this.messageId = messageId;
			this.chatInstance = chatInstance;
			this.payload = payload;
		}

		/**
		 * A new incoming callback query; for bots only.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateNewCallbackQuery(DataInput input) throws IOException {
			this.id = input.readLong();
			this.senderUserId = input.readLong();
			this.chatId = input.readLong();
			this.messageId = input.readLong();
			this.chatInstance = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case CallbackQueryPayloadData.CONSTRUCTOR: this.payload = new CallbackQueryPayloadData(input); break;
					case CallbackQueryPayloadDataWithPassword.CONSTRUCTOR: this.payload = new CallbackQueryPayloadDataWithPassword(input); break;
					case CallbackQueryPayloadGame.CONSTRUCTOR: this.payload = new CallbackQueryPayloadGame(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateNewCallbackQuery.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateNewCallbackQuery.CONSTRUCTOR);
			output.writeLong(this.id);
			output.writeLong(this.senderUserId);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
			output.writeLong(this.chatInstance);
			if (this.payload == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.payload.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateNewCallbackQuery updateNewCallbackQuery = (UpdateNewCallbackQuery) o;
			if (this.id != updateNewCallbackQuery.id) {
				return false;
			}
			if (this.senderUserId != updateNewCallbackQuery.senderUserId) {
				return false;
			}
			if (this.chatId != updateNewCallbackQuery.chatId) {
				return false;
			}
			if (this.messageId != updateNewCallbackQuery.messageId) {
				return false;
			}
			if (this.chatInstance != updateNewCallbackQuery.chatInstance) {
				return false;
			}
			if (!Objects.equals(this.payload, updateNewCallbackQuery.payload)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.id);
			result = result * 31 + (this.payload == null ? 0 : this.payload.hashCode());
			return result;
		}
	}

	/**
	 * A new incoming callback query from a message sent via a bot; for bots
	 * only.
	**/
	public static final class UpdateNewInlineCallbackQuery extends Update {


		/**
		 * Unique query identifier.
		**/
		public long id;

		/**
		 * Identifier of the user who sent the query.
		**/
		public long senderUserId;

		/**
		 * Identifier of the inline message from which the query originated.
		**/
		public String inlineMessageId;

		/**
		 * An identifier uniquely corresponding to the chat a message was sent to.
		**/
		public long chatInstance;

		/**
		 * Query payload.
		**/
		public CallbackQueryPayload payload;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -319212358;

		/**
		 * A new incoming callback query from a message sent via a bot; for bots only.
		**/
		public UpdateNewInlineCallbackQuery() {}

		/**
		 * A new incoming callback query from a message sent via a bot; for bots only.
		 *
		 * @param id Unique query identifier.
		 * @param senderUserId Identifier of the user who sent the query.
		 * @param inlineMessageId Identifier of the inline message from which the query originated.
		 * @param chatInstance An identifier uniquely corresponding to the chat a message was sent to.
		 * @param payload Query payload.
		**/
		public UpdateNewInlineCallbackQuery(long id,
				long senderUserId,
				String inlineMessageId,
				long chatInstance,
				CallbackQueryPayload payload) {
			this.id = id;
			this.senderUserId = senderUserId;
			this.inlineMessageId = inlineMessageId;
			this.chatInstance = chatInstance;
			this.payload = payload;
		}

		/**
		 * A new incoming callback query from a message sent via a bot; for bots only.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateNewInlineCallbackQuery(DataInput input) throws IOException {
			this.id = input.readLong();
			this.senderUserId = input.readLong();
			if (input.readBoolean()) {
				byte[] inlineMessageIdTmp = new byte[input.readInt()];
				input.readFully(inlineMessageIdTmp);
				this.inlineMessageId = new String(inlineMessageIdTmp, StandardCharsets.UTF_8);
			}
			this.chatInstance = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case CallbackQueryPayloadData.CONSTRUCTOR: this.payload = new CallbackQueryPayloadData(input); break;
					case CallbackQueryPayloadDataWithPassword.CONSTRUCTOR: this.payload = new CallbackQueryPayloadDataWithPassword(input); break;
					case CallbackQueryPayloadGame.CONSTRUCTOR: this.payload = new CallbackQueryPayloadGame(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateNewInlineCallbackQuery.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateNewInlineCallbackQuery.CONSTRUCTOR);
			output.writeLong(this.id);
			output.writeLong(this.senderUserId);
			if (this.inlineMessageId == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] inlineMessageIdTmp = this.inlineMessageId.getBytes(StandardCharsets.UTF_8);
				output.writeInt(inlineMessageIdTmp.length);
				output.write(inlineMessageIdTmp);
			}
			output.writeLong(this.chatInstance);
			if (this.payload == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.payload.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateNewInlineCallbackQuery updateNewInlineCallbackQuery = (UpdateNewInlineCallbackQuery) o;
			if (this.id != updateNewInlineCallbackQuery.id) {
				return false;
			}
			if (this.senderUserId != updateNewInlineCallbackQuery.senderUserId) {
				return false;
			}
			if (this.inlineMessageId != updateNewInlineCallbackQuery.inlineMessageId) {
				return false;
			}
			if (this.chatInstance != updateNewInlineCallbackQuery.chatInstance) {
				return false;
			}
			if (!Objects.equals(this.payload, updateNewInlineCallbackQuery.payload)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.id);
			result = result * 31 + (this.inlineMessageId == null ? 0 : this.inlineMessageId.hashCode());
			result = result * 31 + (this.payload == null ? 0 : this.payload.hashCode());
			return result;
		}
	}

	/**
	 * A new incoming shipping query; for bots only. Only for invoices with
	 * flexible price.
	**/
	public static final class UpdateNewShippingQuery extends Update {


		/**
		 * Unique query identifier.
		**/
		public long id;

		/**
		 * Identifier of the user who sent the query.
		**/
		public long senderUserId;

		/**
		 * Invoice payload.
		**/
		public String invoicePayload;

		/**
		 * User shipping address.
		**/
		public Address shippingAddress;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 693651058;

		/**
		 * A new incoming shipping query; for bots only. Only for invoices with flexible price.
		**/
		public UpdateNewShippingQuery() {}

		/**
		 * A new incoming shipping query; for bots only. Only for invoices with flexible price.
		 *
		 * @param id Unique query identifier.
		 * @param senderUserId Identifier of the user who sent the query.
		 * @param invoicePayload Invoice payload.
		 * @param shippingAddress User shipping address.
		**/
		public UpdateNewShippingQuery(long id,
				long senderUserId,
				String invoicePayload,
				Address shippingAddress) {
			this.id = id;
			this.senderUserId = senderUserId;
			this.invoicePayload = invoicePayload;
			this.shippingAddress = shippingAddress;
		}

		/**
		 * A new incoming shipping query; for bots only. Only for invoices with flexible price.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateNewShippingQuery(DataInput input) throws IOException {
			this.id = input.readLong();
			this.senderUserId = input.readLong();
			if (input.readBoolean()) {
				byte[] invoicePayloadTmp = new byte[input.readInt()];
				input.readFully(invoicePayloadTmp);
				this.invoicePayload = new String(invoicePayloadTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (Address.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.shippingAddress = new Address(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateNewShippingQuery.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateNewShippingQuery.CONSTRUCTOR);
			output.writeLong(this.id);
			output.writeLong(this.senderUserId);
			if (this.invoicePayload == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] invoicePayloadTmp = this.invoicePayload.getBytes(StandardCharsets.UTF_8);
				output.writeInt(invoicePayloadTmp.length);
				output.write(invoicePayloadTmp);
			}
			if (this.shippingAddress == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.shippingAddress.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateNewShippingQuery updateNewShippingQuery = (UpdateNewShippingQuery) o;
			if (this.id != updateNewShippingQuery.id) {
				return false;
			}
			if (this.senderUserId != updateNewShippingQuery.senderUserId) {
				return false;
			}
			if (this.invoicePayload != updateNewShippingQuery.invoicePayload) {
				return false;
			}
			if (!Objects.equals(this.shippingAddress, updateNewShippingQuery.shippingAddress)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.id);
			result = result * 31 + (this.invoicePayload == null ? 0 : this.invoicePayload.hashCode());
			result = result * 31 + (this.shippingAddress == null ? 0 : this.shippingAddress.hashCode());
			return result;
		}
	}

	/**
	 * A new incoming pre-checkout query; for bots only. Contains full
	 * information about a checkout.
	**/
	public static final class UpdateNewPreCheckoutQuery extends Update {


		/**
		 * Unique query identifier.
		**/
		public long id;

		/**
		 * Identifier of the user who sent the query.
		**/
		public long senderUserId;

		/**
		 * Currency for the product price.
		**/
		public String currency;

		/**
		 * Total price for the product, in the smallest units of the currency.
		**/
		public long totalAmount;

		/**
		 * Invoice payload.
		**/
		public byte[] invoicePayload;

		/**
		 * Identifier of a shipping option chosen by the user; may be empty if not applicable.
		**/
		public String shippingOptionId;

		/**
		 * Information about the order; may be null.
		**/
		public OrderInfo orderInfo;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 708342217;

		/**
		 * A new incoming pre-checkout query; for bots only. Contains full information about a checkout.
		**/
		public UpdateNewPreCheckoutQuery() {}

		/**
		 * A new incoming pre-checkout query; for bots only. Contains full information about a checkout.
		 *
		 * @param id Unique query identifier.
		 * @param senderUserId Identifier of the user who sent the query.
		 * @param currency Currency for the product price.
		 * @param totalAmount Total price for the product, in the smallest units of the currency.
		 * @param invoicePayload Invoice payload.
		 * @param shippingOptionId Identifier of a shipping option chosen by the user; may be empty if not applicable.
		 * @param orderInfo Information about the order; may be null.
		**/
		public UpdateNewPreCheckoutQuery(long id,
				long senderUserId,
				String currency,
				long totalAmount,
				byte[] invoicePayload,
				String shippingOptionId,
				OrderInfo orderInfo) {
			this.id = id;
			this.senderUserId = senderUserId;
			this.currency = currency;
			this.totalAmount = totalAmount;
			this.invoicePayload = invoicePayload;
			this.shippingOptionId = shippingOptionId;
			this.orderInfo = orderInfo;
		}

		/**
		 * A new incoming pre-checkout query; for bots only. Contains full information about a checkout.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateNewPreCheckoutQuery(DataInput input) throws IOException {
			this.id = input.readLong();
			this.senderUserId = input.readLong();
			if (input.readBoolean()) {
				byte[] currencyTmp = new byte[input.readInt()];
				input.readFully(currencyTmp);
				this.currency = new String(currencyTmp, StandardCharsets.UTF_8);
			}
			this.totalAmount = input.readLong();
			if (input.readBoolean()) {
				this.invoicePayload = new byte[input.readInt()];
				input.readFully(this.invoicePayload);
			}
			if (input.readBoolean()) {
				byte[] shippingOptionIdTmp = new byte[input.readInt()];
				input.readFully(shippingOptionIdTmp);
				this.shippingOptionId = new String(shippingOptionIdTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (OrderInfo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.orderInfo = new OrderInfo(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateNewPreCheckoutQuery.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateNewPreCheckoutQuery.CONSTRUCTOR);
			output.writeLong(this.id);
			output.writeLong(this.senderUserId);
			if (this.currency == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] currencyTmp = this.currency.getBytes(StandardCharsets.UTF_8);
				output.writeInt(currencyTmp.length);
				output.write(currencyTmp);
			}
			output.writeLong(this.totalAmount);
			if (this.invoicePayload == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.invoicePayload.length);
				output.write(this.invoicePayload);
			}
			if (this.shippingOptionId == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] shippingOptionIdTmp = this.shippingOptionId.getBytes(StandardCharsets.UTF_8);
				output.writeInt(shippingOptionIdTmp.length);
				output.write(shippingOptionIdTmp);
			}
			if (this.orderInfo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.orderInfo.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateNewPreCheckoutQuery updateNewPreCheckoutQuery = (UpdateNewPreCheckoutQuery) o;
			if (this.id != updateNewPreCheckoutQuery.id) {
				return false;
			}
			if (this.senderUserId != updateNewPreCheckoutQuery.senderUserId) {
				return false;
			}
			if (this.currency != updateNewPreCheckoutQuery.currency) {
				return false;
			}
			if (this.totalAmount != updateNewPreCheckoutQuery.totalAmount) {
				return false;
			}
			if (this.invoicePayload != updateNewPreCheckoutQuery.invoicePayload) {
				return false;
			}
			if (this.shippingOptionId != updateNewPreCheckoutQuery.shippingOptionId) {
				return false;
			}
			if (!Objects.equals(this.orderInfo, updateNewPreCheckoutQuery.orderInfo)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.id);
			result = result * 31 + (this.currency == null ? 0 : this.currency.hashCode());
			result = result * 31 + (Arrays.hashCode(this.invoicePayload));
			result = result * 31 + (this.shippingOptionId == null ? 0 : this.shippingOptionId.hashCode());
			result = result * 31 + (this.orderInfo == null ? 0 : this.orderInfo.hashCode());
			return result;
		}
	}

	/**
	 * A new incoming event; for bots only.
	**/
	public static final class UpdateNewCustomEvent extends Update {


		/**
		 * A JSON-serialized event.
		**/
		public String event;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1994222092;

		/**
		 * A new incoming event; for bots only.
		**/
		public UpdateNewCustomEvent() {}

		/**
		 * A new incoming event; for bots only.
		 *
		 * @param event A JSON-serialized event.
		**/
		public UpdateNewCustomEvent(String event) {
			this.event = event;
		}

		/**
		 * A new incoming event; for bots only.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateNewCustomEvent(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] eventTmp = new byte[input.readInt()];
				input.readFully(eventTmp);
				this.event = new String(eventTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateNewCustomEvent.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateNewCustomEvent.CONSTRUCTOR);
			if (this.event == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] eventTmp = this.event.getBytes(StandardCharsets.UTF_8);
				output.writeInt(eventTmp.length);
				output.write(eventTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateNewCustomEvent updateNewCustomEvent = (UpdateNewCustomEvent) o;
			if (this.event != updateNewCustomEvent.event) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.event == null ? 0 : this.event.hashCode();
		}
	}

	/**
	 * A new incoming query; for bots only.
	**/
	public static final class UpdateNewCustomQuery extends Update {


		/**
		 * The query identifier.
		**/
		public long id;

		/**
		 * JSON-serialized query data.
		**/
		public String data;

		/**
		 * Query timeout.
		**/
		public int timeout;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -687670874;

		/**
		 * A new incoming query; for bots only.
		**/
		public UpdateNewCustomQuery() {}

		/**
		 * A new incoming query; for bots only.
		 *
		 * @param id The query identifier.
		 * @param data JSON-serialized query data.
		 * @param timeout Query timeout.
		**/
		public UpdateNewCustomQuery(long id, String data, int timeout) {
			this.id = id;
			this.data = data;
			this.timeout = timeout;
		}

		/**
		 * A new incoming query; for bots only.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateNewCustomQuery(DataInput input) throws IOException {
			this.id = input.readLong();
			if (input.readBoolean()) {
				byte[] dataTmp = new byte[input.readInt()];
				input.readFully(dataTmp);
				this.data = new String(dataTmp, StandardCharsets.UTF_8);
			}
			this.timeout = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateNewCustomQuery.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateNewCustomQuery.CONSTRUCTOR);
			output.writeLong(this.id);
			if (this.data == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] dataTmp = this.data.getBytes(StandardCharsets.UTF_8);
				output.writeInt(dataTmp.length);
				output.write(dataTmp);
			}
			output.writeInt(this.timeout);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateNewCustomQuery updateNewCustomQuery = (UpdateNewCustomQuery) o;
			if (this.id != updateNewCustomQuery.id) {
				return false;
			}
			if (this.data != updateNewCustomQuery.data) {
				return false;
			}
			if (this.timeout != updateNewCustomQuery.timeout) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.id);
			result = result * 31 + (this.data == null ? 0 : this.data.hashCode());
			return result;
		}
	}

	/**
	 * A poll was updated; for bots only.
	**/
	public static final class UpdatePoll extends Update {


		/**
		 * New data about the poll.
		**/
		public Poll poll;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1771342902;

		/**
		 * A poll was updated; for bots only.
		**/
		public UpdatePoll() {}

		/**
		 * A poll was updated; for bots only.
		 *
		 * @param poll New data about the poll.
		**/
		public UpdatePoll(Poll poll) {
			this.poll = poll;
		}

		/**
		 * A poll was updated; for bots only.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdatePoll(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Poll.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.poll = new Poll(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdatePoll.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdatePoll.CONSTRUCTOR);
			if (this.poll == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.poll.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdatePoll updatePoll = (UpdatePoll) o;
			if (!Objects.equals(this.poll, updatePoll.poll)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.poll == null ? 0 : this.poll.hashCode();
		}
	}

	/**
	 * A user changed the answer to a poll; for bots only.
	**/
	public static final class UpdatePollAnswer extends Update {


		/**
		 * Unique poll identifier.
		**/
		public long pollId;

		/**
		 * The user, who changed the answer to the poll.
		**/
		public long userId;

		/**
		 * 0-based identifiers of answer options, chosen by the user.
		**/
		public int[] optionIds;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1209100651;

		/**
		 * A user changed the answer to a poll; for bots only.
		**/
		public UpdatePollAnswer() {}

		/**
		 * A user changed the answer to a poll; for bots only.
		 *
		 * @param pollId Unique poll identifier.
		 * @param userId The user, who changed the answer to the poll.
		 * @param optionIds 0-based identifiers of answer options, chosen by the user.
		**/
		public UpdatePollAnswer(long pollId, long userId, int[] optionIds) {
			this.pollId = pollId;
			this.userId = userId;
			this.optionIds = optionIds;
		}

		/**
		 * A user changed the answer to a poll; for bots only.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdatePollAnswer(DataInput input) throws IOException {
			this.pollId = input.readLong();
			this.userId = input.readLong();
			if (input.readBoolean()) {
				this.optionIds = new int[input.readInt()];
				for (int i = 0; i < this.optionIds.length; i++) {
					this.optionIds[i] = input.readInt();
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdatePollAnswer.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdatePollAnswer.CONSTRUCTOR);
			output.writeLong(this.pollId);
			output.writeLong(this.userId);
			if (this.optionIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.optionIds.length);
				for (int i = 0; i < this.optionIds.length; i++) {
					output.writeInt(this.optionIds[i]);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdatePollAnswer updatePollAnswer = (UpdatePollAnswer) o;
			if (this.pollId != updatePollAnswer.pollId) {
				return false;
			}
			if (this.userId != updatePollAnswer.userId) {
				return false;
			}
			if (!Arrays.equals(this.optionIds, updatePollAnswer.optionIds)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.pollId);
			result = result * 31 + (Arrays.hashCode(this.optionIds));
			return result;
		}
	}

	/**
	 * User rights changed in a chat; for bots only.
	**/
	public static final class UpdateChatMember extends Update {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Identifier of the user, changing the rights.
		**/
		public long actorUserId;

		/**
		 * Point in time (Unix timestamp) when the user rights was changed.
		**/
		public int date;

		/**
		 * If user has joined the chat using an invite link, the invite link; may be null.
		**/
		public ChatInviteLink inviteLink;

		/**
		 * True, if the user has joined the chat using an invite link for a chat folder.
		**/
		public boolean viaChatFolderInviteLink;

		/**
		 * Previous chat member.
		**/
		public ChatMember oldChatMember;

		/**
		 * New chat member.
		**/
		public ChatMember newChatMember;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1610670748;

		/**
		 * User rights changed in a chat; for bots only.
		**/
		public UpdateChatMember() {}

		/**
		 * User rights changed in a chat; for bots only.
		 *
		 * @param chatId Chat identifier.
		 * @param actorUserId Identifier of the user, changing the rights.
		 * @param date Point in time (Unix timestamp) when the user rights was changed.
		 * @param inviteLink If user has joined the chat using an invite link, the invite link; may be null.
		 * @param viaChatFolderInviteLink True, if the user has joined the chat using an invite link for a chat folder.
		 * @param oldChatMember Previous chat member.
		 * @param newChatMember New chat member.
		**/
		public UpdateChatMember(long chatId,
				long actorUserId,
				int date,
				ChatInviteLink inviteLink,
				boolean viaChatFolderInviteLink,
				ChatMember oldChatMember,
				ChatMember newChatMember) {
			this.chatId = chatId;
			this.actorUserId = actorUserId;
			this.date = date;
			this.inviteLink = inviteLink;
			this.viaChatFolderInviteLink = viaChatFolderInviteLink;
			this.oldChatMember = oldChatMember;
			this.newChatMember = newChatMember;
		}

		/**
		 * User rights changed in a chat; for bots only.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateChatMember(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.actorUserId = input.readLong();
			this.date = input.readInt();
			if (input.readBoolean()) {
				if (ChatInviteLink.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.inviteLink = new ChatInviteLink(input);
			}
			this.viaChatFolderInviteLink = input.readBoolean();
			if (input.readBoolean()) {
				if (ChatMember.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.oldChatMember = new ChatMember(input);
			}
			if (input.readBoolean()) {
				if (ChatMember.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.newChatMember = new ChatMember(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateChatMember.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateChatMember.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.actorUserId);
			output.writeInt(this.date);
			if (this.inviteLink == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.inviteLink.serialize(output);
			}
			output.writeBoolean(this.viaChatFolderInviteLink);
			if (this.oldChatMember == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.oldChatMember.serialize(output);
			}
			if (this.newChatMember == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.newChatMember.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateChatMember updateChatMember = (UpdateChatMember) o;
			if (this.chatId != updateChatMember.chatId) {
				return false;
			}
			if (this.actorUserId != updateChatMember.actorUserId) {
				return false;
			}
			if (this.date != updateChatMember.date) {
				return false;
			}
			if (!Objects.equals(this.inviteLink, updateChatMember.inviteLink)) {
				return false;
			}
			if (this.viaChatFolderInviteLink != updateChatMember.viaChatFolderInviteLink) {
				return false;
			}
			if (!Objects.equals(this.oldChatMember, updateChatMember.oldChatMember)) {
				return false;
			}
			if (!Objects.equals(this.newChatMember, updateChatMember.newChatMember)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.inviteLink == null ? 0 : this.inviteLink.hashCode());
			result = result * 31 + (this.oldChatMember == null ? 0 : this.oldChatMember.hashCode());
			result = result * 31 + (this.newChatMember == null ? 0 : this.newChatMember.hashCode());
			return result;
		}
	}

	/**
	 * A user sent a join request to a chat; for bots only.
	**/
	public static final class UpdateNewChatJoinRequest extends Update {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Join request.
		**/
		public ChatJoinRequest request;

		/**
		 * Chat identifier of the private chat with the user.
		**/
		public long userChatId;

		/**
		 * The invite link, which was used to send join request; may be null.
		**/
		public ChatInviteLink inviteLink;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2118694979;

		/**
		 * A user sent a join request to a chat; for bots only.
		**/
		public UpdateNewChatJoinRequest() {}

		/**
		 * A user sent a join request to a chat; for bots only.
		 *
		 * @param chatId Chat identifier.
		 * @param request Join request.
		 * @param userChatId Chat identifier of the private chat with the user.
		 * @param inviteLink The invite link, which was used to send join request; may be null.
		**/
		public UpdateNewChatJoinRequest(long chatId,
				ChatJoinRequest request,
				long userChatId,
				ChatInviteLink inviteLink) {
			this.chatId = chatId;
			this.request = request;
			this.userChatId = userChatId;
			this.inviteLink = inviteLink;
		}

		/**
		 * A user sent a join request to a chat; for bots only.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpdateNewChatJoinRequest(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				if (ChatJoinRequest.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.request = new ChatJoinRequest(input);
			}
			this.userChatId = input.readLong();
			if (input.readBoolean()) {
				if (ChatInviteLink.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.inviteLink = new ChatInviteLink(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpdateNewChatJoinRequest.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpdateNewChatJoinRequest.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.request == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.request.serialize(output);
			}
			output.writeLong(this.userChatId);
			if (this.inviteLink == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.inviteLink.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpdateNewChatJoinRequest updateNewChatJoinRequest = (UpdateNewChatJoinRequest) o;
			if (this.chatId != updateNewChatJoinRequest.chatId) {
				return false;
			}
			if (!Objects.equals(this.request, updateNewChatJoinRequest.request)) {
				return false;
			}
			if (this.userChatId != updateNewChatJoinRequest.userChatId) {
				return false;
			}
			if (!Objects.equals(this.inviteLink, updateNewChatJoinRequest.inviteLink)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.request == null ? 0 : this.request.hashCode());
			result = result * 31 + (this.inviteLink == null ? 0 : this.inviteLink.hashCode());
			return result;
		}
	}

	/**
	 * Contains a list of updates.
	**/
	public static final class Updates extends Object {


		/**
		 * List of updates.
		**/
		public Update[] updates;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 475842347;

		/**
		 * Contains a list of updates.
		**/
		public Updates() {}

		/**
		 * Contains a list of updates.
		 *
		 * @param updates List of updates.
		**/
		public Updates(Update[] updates) {
			this.updates = updates;
		}

		/**
		 * Contains a list of updates.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public Updates(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.updates = new Update[input.readInt()];
				for (int i = 0; i < this.updates.length; i++) {
					switch(input.readInt()) {
						case UpdateAuthorizationState.CONSTRUCTOR: this.updates[i] = new UpdateAuthorizationState(input); break;
						case UpdateNewMessage.CONSTRUCTOR: this.updates[i] = new UpdateNewMessage(input); break;
						case UpdateMessageSendAcknowledged.CONSTRUCTOR: this.updates[i] = new UpdateMessageSendAcknowledged(input); break;
						case UpdateMessageSendSucceeded.CONSTRUCTOR: this.updates[i] = new UpdateMessageSendSucceeded(input); break;
						case UpdateMessageSendFailed.CONSTRUCTOR: this.updates[i] = new UpdateMessageSendFailed(input); break;
						case UpdateMessageContent.CONSTRUCTOR: this.updates[i] = new UpdateMessageContent(input); break;
						case UpdateMessageEdited.CONSTRUCTOR: this.updates[i] = new UpdateMessageEdited(input); break;
						case UpdateMessageIsPinned.CONSTRUCTOR: this.updates[i] = new UpdateMessageIsPinned(input); break;
						case UpdateMessageInteractionInfo.CONSTRUCTOR: this.updates[i] = new UpdateMessageInteractionInfo(input); break;
						case UpdateMessageContentOpened.CONSTRUCTOR: this.updates[i] = new UpdateMessageContentOpened(input); break;
						case UpdateMessageMentionRead.CONSTRUCTOR: this.updates[i] = new UpdateMessageMentionRead(input); break;
						case UpdateMessageUnreadReactions.CONSTRUCTOR: this.updates[i] = new UpdateMessageUnreadReactions(input); break;
						case UpdateMessageLiveLocationViewed.CONSTRUCTOR: this.updates[i] = new UpdateMessageLiveLocationViewed(input); break;
						case UpdateNewChat.CONSTRUCTOR: this.updates[i] = new UpdateNewChat(input); break;
						case UpdateChatTitle.CONSTRUCTOR: this.updates[i] = new UpdateChatTitle(input); break;
						case UpdateChatPhoto.CONSTRUCTOR: this.updates[i] = new UpdateChatPhoto(input); break;
						case UpdateChatPermissions.CONSTRUCTOR: this.updates[i] = new UpdateChatPermissions(input); break;
						case UpdateChatLastMessage.CONSTRUCTOR: this.updates[i] = new UpdateChatLastMessage(input); break;
						case UpdateChatPosition.CONSTRUCTOR: this.updates[i] = new UpdateChatPosition(input); break;
						case UpdateChatReadInbox.CONSTRUCTOR: this.updates[i] = new UpdateChatReadInbox(input); break;
						case UpdateChatReadOutbox.CONSTRUCTOR: this.updates[i] = new UpdateChatReadOutbox(input); break;
						case UpdateChatActionBar.CONSTRUCTOR: this.updates[i] = new UpdateChatActionBar(input); break;
						case UpdateChatAvailableReactions.CONSTRUCTOR: this.updates[i] = new UpdateChatAvailableReactions(input); break;
						case UpdateChatDraftMessage.CONSTRUCTOR: this.updates[i] = new UpdateChatDraftMessage(input); break;
						case UpdateChatMessageSender.CONSTRUCTOR: this.updates[i] = new UpdateChatMessageSender(input); break;
						case UpdateChatMessageAutoDeleteTime.CONSTRUCTOR: this.updates[i] = new UpdateChatMessageAutoDeleteTime(input); break;
						case UpdateChatNotificationSettings.CONSTRUCTOR: this.updates[i] = new UpdateChatNotificationSettings(input); break;
						case UpdateChatPendingJoinRequests.CONSTRUCTOR: this.updates[i] = new UpdateChatPendingJoinRequests(input); break;
						case UpdateChatReplyMarkup.CONSTRUCTOR: this.updates[i] = new UpdateChatReplyMarkup(input); break;
						case UpdateChatBackground.CONSTRUCTOR: this.updates[i] = new UpdateChatBackground(input); break;
						case UpdateChatTheme.CONSTRUCTOR: this.updates[i] = new UpdateChatTheme(input); break;
						case UpdateChatUnreadMentionCount.CONSTRUCTOR: this.updates[i] = new UpdateChatUnreadMentionCount(input); break;
						case UpdateChatUnreadReactionCount.CONSTRUCTOR: this.updates[i] = new UpdateChatUnreadReactionCount(input); break;
						case UpdateChatVideoChat.CONSTRUCTOR: this.updates[i] = new UpdateChatVideoChat(input); break;
						case UpdateChatDefaultDisableNotification.CONSTRUCTOR: this.updates[i] = new UpdateChatDefaultDisableNotification(input); break;
						case UpdateChatHasProtectedContent.CONSTRUCTOR: this.updates[i] = new UpdateChatHasProtectedContent(input); break;
						case UpdateChatIsTranslatable.CONSTRUCTOR: this.updates[i] = new UpdateChatIsTranslatable(input); break;
						case UpdateChatIsMarkedAsUnread.CONSTRUCTOR: this.updates[i] = new UpdateChatIsMarkedAsUnread(input); break;
						case UpdateChatIsBlocked.CONSTRUCTOR: this.updates[i] = new UpdateChatIsBlocked(input); break;
						case UpdateChatHasScheduledMessages.CONSTRUCTOR: this.updates[i] = new UpdateChatHasScheduledMessages(input); break;
						case UpdateChatFolders.CONSTRUCTOR: this.updates[i] = new UpdateChatFolders(input); break;
						case UpdateChatOnlineMemberCount.CONSTRUCTOR: this.updates[i] = new UpdateChatOnlineMemberCount(input); break;
						case UpdateForumTopicInfo.CONSTRUCTOR: this.updates[i] = new UpdateForumTopicInfo(input); break;
						case UpdateScopeNotificationSettings.CONSTRUCTOR: this.updates[i] = new UpdateScopeNotificationSettings(input); break;
						case UpdateNotification.CONSTRUCTOR: this.updates[i] = new UpdateNotification(input); break;
						case UpdateNotificationGroup.CONSTRUCTOR: this.updates[i] = new UpdateNotificationGroup(input); break;
						case UpdateActiveNotifications.CONSTRUCTOR: this.updates[i] = new UpdateActiveNotifications(input); break;
						case UpdateHavePendingNotifications.CONSTRUCTOR: this.updates[i] = new UpdateHavePendingNotifications(input); break;
						case UpdateDeleteMessages.CONSTRUCTOR: this.updates[i] = new UpdateDeleteMessages(input); break;
						case UpdateChatAction.CONSTRUCTOR: this.updates[i] = new UpdateChatAction(input); break;
						case UpdateUserStatus.CONSTRUCTOR: this.updates[i] = new UpdateUserStatus(input); break;
						case UpdateUser.CONSTRUCTOR: this.updates[i] = new UpdateUser(input); break;
						case UpdateAccessHash.CONSTRUCTOR: this.updates[i] = new UpdateAccessHash(input); break;
						case UpdateBasicGroup.CONSTRUCTOR: this.updates[i] = new UpdateBasicGroup(input); break;
						case UpdateSupergroup.CONSTRUCTOR: this.updates[i] = new UpdateSupergroup(input); break;
						case UpdateSecretChat.CONSTRUCTOR: this.updates[i] = new UpdateSecretChat(input); break;
						case UpdateUserFullInfo.CONSTRUCTOR: this.updates[i] = new UpdateUserFullInfo(input); break;
						case UpdateBasicGroupFullInfo.CONSTRUCTOR: this.updates[i] = new UpdateBasicGroupFullInfo(input); break;
						case UpdateSupergroupFullInfo.CONSTRUCTOR: this.updates[i] = new UpdateSupergroupFullInfo(input); break;
						case UpdateServiceNotification.CONSTRUCTOR: this.updates[i] = new UpdateServiceNotification(input); break;
						case UpdateFile.CONSTRUCTOR: this.updates[i] = new UpdateFile(input); break;
						case UpdateFileGenerationStart.CONSTRUCTOR: this.updates[i] = new UpdateFileGenerationStart(input); break;
						case UpdateFileGenerationStop.CONSTRUCTOR: this.updates[i] = new UpdateFileGenerationStop(input); break;
						case UpdateFileDownloads.CONSTRUCTOR: this.updates[i] = new UpdateFileDownloads(input); break;
						case UpdateFileAddedToDownloads.CONSTRUCTOR: this.updates[i] = new UpdateFileAddedToDownloads(input); break;
						case UpdateFileDownload.CONSTRUCTOR: this.updates[i] = new UpdateFileDownload(input); break;
						case UpdateFileRemovedFromDownloads.CONSTRUCTOR: this.updates[i] = new UpdateFileRemovedFromDownloads(input); break;
						case UpdateCall.CONSTRUCTOR: this.updates[i] = new UpdateCall(input); break;
						case UpdateGroupCall.CONSTRUCTOR: this.updates[i] = new UpdateGroupCall(input); break;
						case UpdateGroupCallParticipant.CONSTRUCTOR: this.updates[i] = new UpdateGroupCallParticipant(input); break;
						case UpdateNewCallSignalingData.CONSTRUCTOR: this.updates[i] = new UpdateNewCallSignalingData(input); break;
						case UpdateUserPrivacySettingRules.CONSTRUCTOR: this.updates[i] = new UpdateUserPrivacySettingRules(input); break;
						case UpdateUnreadMessageCount.CONSTRUCTOR: this.updates[i] = new UpdateUnreadMessageCount(input); break;
						case UpdateUnreadChatCount.CONSTRUCTOR: this.updates[i] = new UpdateUnreadChatCount(input); break;
						case UpdateOption.CONSTRUCTOR: this.updates[i] = new UpdateOption(input); break;
						case UpdateStickerSet.CONSTRUCTOR: this.updates[i] = new UpdateStickerSet(input); break;
						case UpdateInstalledStickerSets.CONSTRUCTOR: this.updates[i] = new UpdateInstalledStickerSets(input); break;
						case UpdateTrendingStickerSets.CONSTRUCTOR: this.updates[i] = new UpdateTrendingStickerSets(input); break;
						case UpdateRecentStickers.CONSTRUCTOR: this.updates[i] = new UpdateRecentStickers(input); break;
						case UpdateFavoriteStickers.CONSTRUCTOR: this.updates[i] = new UpdateFavoriteStickers(input); break;
						case UpdateSavedAnimations.CONSTRUCTOR: this.updates[i] = new UpdateSavedAnimations(input); break;
						case UpdateSavedNotificationSounds.CONSTRUCTOR: this.updates[i] = new UpdateSavedNotificationSounds(input); break;
						case UpdateSelectedBackground.CONSTRUCTOR: this.updates[i] = new UpdateSelectedBackground(input); break;
						case UpdateChatThemes.CONSTRUCTOR: this.updates[i] = new UpdateChatThemes(input); break;
						case UpdateLanguagePackStrings.CONSTRUCTOR: this.updates[i] = new UpdateLanguagePackStrings(input); break;
						case UpdateConnectionState.CONSTRUCTOR: this.updates[i] = new UpdateConnectionState(input); break;
						case UpdateTermsOfService.CONSTRUCTOR: this.updates[i] = new UpdateTermsOfService(input); break;
						case UpdateUsersNearby.CONSTRUCTOR: this.updates[i] = new UpdateUsersNearby(input); break;
						case UpdateAttachmentMenuBots.CONSTRUCTOR: this.updates[i] = new UpdateAttachmentMenuBots(input); break;
						case UpdateWebAppMessageSent.CONSTRUCTOR: this.updates[i] = new UpdateWebAppMessageSent(input); break;
						case UpdateActiveEmojiReactions.CONSTRUCTOR: this.updates[i] = new UpdateActiveEmojiReactions(input); break;
						case UpdateDefaultReactionType.CONSTRUCTOR: this.updates[i] = new UpdateDefaultReactionType(input); break;
						case UpdateDiceEmojis.CONSTRUCTOR: this.updates[i] = new UpdateDiceEmojis(input); break;
						case UpdateAnimatedEmojiMessageClicked.CONSTRUCTOR: this.updates[i] = new UpdateAnimatedEmojiMessageClicked(input); break;
						case UpdateAnimationSearchParameters.CONSTRUCTOR: this.updates[i] = new UpdateAnimationSearchParameters(input); break;
						case UpdateSuggestedActions.CONSTRUCTOR: this.updates[i] = new UpdateSuggestedActions(input); break;
						case UpdateAddChatMembersPrivacyForbidden.CONSTRUCTOR: this.updates[i] = new UpdateAddChatMembersPrivacyForbidden(input); break;
						case UpdateAutosaveSettings.CONSTRUCTOR: this.updates[i] = new UpdateAutosaveSettings(input); break;
						case UpdateNewInlineQuery.CONSTRUCTOR: this.updates[i] = new UpdateNewInlineQuery(input); break;
						case UpdateNewChosenInlineResult.CONSTRUCTOR: this.updates[i] = new UpdateNewChosenInlineResult(input); break;
						case UpdateNewCallbackQuery.CONSTRUCTOR: this.updates[i] = new UpdateNewCallbackQuery(input); break;
						case UpdateNewInlineCallbackQuery.CONSTRUCTOR: this.updates[i] = new UpdateNewInlineCallbackQuery(input); break;
						case UpdateNewShippingQuery.CONSTRUCTOR: this.updates[i] = new UpdateNewShippingQuery(input); break;
						case UpdateNewPreCheckoutQuery.CONSTRUCTOR: this.updates[i] = new UpdateNewPreCheckoutQuery(input); break;
						case UpdateNewCustomEvent.CONSTRUCTOR: this.updates[i] = new UpdateNewCustomEvent(input); break;
						case UpdateNewCustomQuery.CONSTRUCTOR: this.updates[i] = new UpdateNewCustomQuery(input); break;
						case UpdatePoll.CONSTRUCTOR: this.updates[i] = new UpdatePoll(input); break;
						case UpdatePollAnswer.CONSTRUCTOR: this.updates[i] = new UpdatePollAnswer(input); break;
						case UpdateChatMember.CONSTRUCTOR: this.updates[i] = new UpdateChatMember(input); break;
						case UpdateNewChatJoinRequest.CONSTRUCTOR: this.updates[i] = new UpdateNewChatJoinRequest(input); break;
						default: {
							throw new UnsupportedOperationException();
						}
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return Updates.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(Updates.CONSTRUCTOR);
			if (this.updates == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.updates.length);
				for (int i = 0; i < this.updates.length; i++) {
					this.updates[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			Updates updates = (Updates) o;
			if (!Arrays.equals(this.updates, updates.updates)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.updates);
		}
	}

	/**
	 * Represents a user.
	**/
	public static final class User extends Object {


		/**
		 * User identifier.
		**/
		public long id;

		/**
		 * First name of the user.
		**/
		public String firstName;

		/**
		 * Last name of the user.
		**/
		public String lastName;

		/**
		 * Usernames of the user; may be null.
		**/
		public Usernames usernames;

		/**
		 * Phone number of the user.
		**/
		public String phoneNumber;

		/**
		 * Current online status of the user.
		**/
		public UserStatus status;

		/**
		 * Profile photo of the user; may be null.
		**/
		public ProfilePhoto profilePhoto;

		/**
		 * Emoji status to be shown instead of the default Telegram Premium badge; may be null. For Telegram Premium users only.
		**/
		public EmojiStatus emojiStatus;

		/**
		 * The user is a contact of the current user.
		**/
		public boolean isContact;

		/**
		 * The user is a contact of the current user and the current user is a contact of the user.
		**/
		public boolean isMutualContact;

		/**
		 * True, if the user is verified.
		**/
		public boolean isVerified;

		/**
		 * True, if the user is a Telegram Premium user.
		**/
		public boolean isPremium;

		/**
		 * True, if the user is Telegram support account.
		**/
		public boolean isSupport;

		/**
		 * If non-empty, it contains a human-readable description of the reason why access to this user must be restricted.
		**/
		public String restrictionReason;

		/**
		 * True, if many users reported this user as a scam.
		**/
		public boolean isScam;

		/**
		 * True, if many users reported this user as a fake account.
		**/
		public boolean isFake;

		/**
		 * If false, the user is inaccessible, and the only information known about the user is inside this class. Identifier of the user can&#039;t be passed to any method.
		**/
		public boolean haveAccess;

		/**
		 * Type of the user.
		**/
		public UserType type;

		/**
		 * IETF language tag of the user&#039;s language; only available to bots.
		**/
		public String languageCode;

		/**
		 * True, if the user added the current bot to attachment menu; only available to bots.
		**/
		public boolean addedToAttachmentMenu;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -651883724;

		/**
		 * Represents a user.
		**/
		public User() {}

		/**
		 * Represents a user.
		 *
		 * @param id User identifier.
		 * @param firstName First name of the user.
		 * @param lastName Last name of the user.
		 * @param usernames Usernames of the user; may be null.
		 * @param phoneNumber Phone number of the user.
		 * @param status Current online status of the user.
		 * @param profilePhoto Profile photo of the user; may be null.
		 * @param emojiStatus Emoji status to be shown instead of the default Telegram Premium badge; may be null. For Telegram Premium users only.
		 * @param isContact The user is a contact of the current user.
		 * @param isMutualContact The user is a contact of the current user and the current user is a contact of the user.
		 * @param isVerified True, if the user is verified.
		 * @param isPremium True, if the user is a Telegram Premium user.
		 * @param isSupport True, if the user is Telegram support account.
		 * @param restrictionReason If non-empty, it contains a human-readable description of the reason why access to this user must be restricted.
		 * @param isScam True, if many users reported this user as a scam.
		 * @param isFake True, if many users reported this user as a fake account.
		 * @param haveAccess If false, the user is inaccessible, and the only information known about the user is inside this class. Identifier of the user can&#039;t be passed to any method.
		 * @param type Type of the user.
		 * @param languageCode IETF language tag of the user&#039;s language; only available to bots.
		 * @param addedToAttachmentMenu True, if the user added the current bot to attachment menu; only available to bots.
		**/
		public User(long id,
				String firstName,
				String lastName,
				Usernames usernames,
				String phoneNumber,
				UserStatus status,
				ProfilePhoto profilePhoto,
				EmojiStatus emojiStatus,
				boolean isContact,
				boolean isMutualContact,
				boolean isVerified,
				boolean isPremium,
				boolean isSupport,
				String restrictionReason,
				boolean isScam,
				boolean isFake,
				boolean haveAccess,
				UserType type,
				String languageCode,
				boolean addedToAttachmentMenu) {
			this.id = id;
			this.firstName = firstName;
			this.lastName = lastName;
			this.usernames = usernames;
			this.phoneNumber = phoneNumber;
			this.status = status;
			this.profilePhoto = profilePhoto;
			this.emojiStatus = emojiStatus;
			this.isContact = isContact;
			this.isMutualContact = isMutualContact;
			this.isVerified = isVerified;
			this.isPremium = isPremium;
			this.isSupport = isSupport;
			this.restrictionReason = restrictionReason;
			this.isScam = isScam;
			this.isFake = isFake;
			this.haveAccess = haveAccess;
			this.type = type;
			this.languageCode = languageCode;
			this.addedToAttachmentMenu = addedToAttachmentMenu;
		}

		/**
		 * Represents a user.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public User(DataInput input) throws IOException {
			this.id = input.readLong();
			if (input.readBoolean()) {
				byte[] firstNameTmp = new byte[input.readInt()];
				input.readFully(firstNameTmp);
				this.firstName = new String(firstNameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] lastNameTmp = new byte[input.readInt()];
				input.readFully(lastNameTmp);
				this.lastName = new String(lastNameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (Usernames.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.usernames = new Usernames(input);
			}
			if (input.readBoolean()) {
				byte[] phoneNumberTmp = new byte[input.readInt()];
				input.readFully(phoneNumberTmp);
				this.phoneNumber = new String(phoneNumberTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case UserStatusEmpty.CONSTRUCTOR: this.status = new UserStatusEmpty(input); break;
					case UserStatusOnline.CONSTRUCTOR: this.status = new UserStatusOnline(input); break;
					case UserStatusOffline.CONSTRUCTOR: this.status = new UserStatusOffline(input); break;
					case UserStatusRecently.CONSTRUCTOR: this.status = new UserStatusRecently(input); break;
					case UserStatusLastWeek.CONSTRUCTOR: this.status = new UserStatusLastWeek(input); break;
					case UserStatusLastMonth.CONSTRUCTOR: this.status = new UserStatusLastMonth(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				if (ProfilePhoto.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.profilePhoto = new ProfilePhoto(input);
			}
			if (input.readBoolean()) {
				if (EmojiStatus.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.emojiStatus = new EmojiStatus(input);
			}
			this.isContact = input.readBoolean();
			this.isMutualContact = input.readBoolean();
			this.isVerified = input.readBoolean();
			this.isPremium = input.readBoolean();
			this.isSupport = input.readBoolean();
			if (input.readBoolean()) {
				byte[] restrictionReasonTmp = new byte[input.readInt()];
				input.readFully(restrictionReasonTmp);
				this.restrictionReason = new String(restrictionReasonTmp, StandardCharsets.UTF_8);
			}
			this.isScam = input.readBoolean();
			this.isFake = input.readBoolean();
			this.haveAccess = input.readBoolean();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case UserTypeRegular.CONSTRUCTOR: this.type = new UserTypeRegular(input); break;
					case UserTypeDeleted.CONSTRUCTOR: this.type = new UserTypeDeleted(input); break;
					case UserTypeBot.CONSTRUCTOR: this.type = new UserTypeBot(input); break;
					case UserTypeUnknown.CONSTRUCTOR: this.type = new UserTypeUnknown(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				byte[] languageCodeTmp = new byte[input.readInt()];
				input.readFully(languageCodeTmp);
				this.languageCode = new String(languageCodeTmp, StandardCharsets.UTF_8);
			}
			this.addedToAttachmentMenu = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return User.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(User.CONSTRUCTOR);
			output.writeLong(this.id);
			if (this.firstName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] firstNameTmp = this.firstName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(firstNameTmp.length);
				output.write(firstNameTmp);
			}
			if (this.lastName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] lastNameTmp = this.lastName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(lastNameTmp.length);
				output.write(lastNameTmp);
			}
			if (this.usernames == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.usernames.serialize(output);
			}
			if (this.phoneNumber == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] phoneNumberTmp = this.phoneNumber.getBytes(StandardCharsets.UTF_8);
				output.writeInt(phoneNumberTmp.length);
				output.write(phoneNumberTmp);
			}
			if (this.status == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.status.serialize(output);
			}
			if (this.profilePhoto == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.profilePhoto.serialize(output);
			}
			if (this.emojiStatus == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.emojiStatus.serialize(output);
			}
			output.writeBoolean(this.isContact);
			output.writeBoolean(this.isMutualContact);
			output.writeBoolean(this.isVerified);
			output.writeBoolean(this.isPremium);
			output.writeBoolean(this.isSupport);
			if (this.restrictionReason == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] restrictionReasonTmp = this.restrictionReason.getBytes(StandardCharsets.UTF_8);
				output.writeInt(restrictionReasonTmp.length);
				output.write(restrictionReasonTmp);
			}
			output.writeBoolean(this.isScam);
			output.writeBoolean(this.isFake);
			output.writeBoolean(this.haveAccess);
			if (this.type == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.type.serialize(output);
			}
			if (this.languageCode == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] languageCodeTmp = this.languageCode.getBytes(StandardCharsets.UTF_8);
				output.writeInt(languageCodeTmp.length);
				output.write(languageCodeTmp);
			}
			output.writeBoolean(this.addedToAttachmentMenu);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			User user = (User) o;
			if (this.id != user.id) {
				return false;
			}
			if (this.firstName != user.firstName) {
				return false;
			}
			if (this.lastName != user.lastName) {
				return false;
			}
			if (!Objects.equals(this.usernames, user.usernames)) {
				return false;
			}
			if (this.phoneNumber != user.phoneNumber) {
				return false;
			}
			if (!Objects.equals(this.status, user.status)) {
				return false;
			}
			if (!Objects.equals(this.profilePhoto, user.profilePhoto)) {
				return false;
			}
			if (!Objects.equals(this.emojiStatus, user.emojiStatus)) {
				return false;
			}
			if (this.isContact != user.isContact) {
				return false;
			}
			if (this.isMutualContact != user.isMutualContact) {
				return false;
			}
			if (this.isVerified != user.isVerified) {
				return false;
			}
			if (this.isPremium != user.isPremium) {
				return false;
			}
			if (this.isSupport != user.isSupport) {
				return false;
			}
			if (this.restrictionReason != user.restrictionReason) {
				return false;
			}
			if (this.isScam != user.isScam) {
				return false;
			}
			if (this.isFake != user.isFake) {
				return false;
			}
			if (this.haveAccess != user.haveAccess) {
				return false;
			}
			if (!Objects.equals(this.type, user.type)) {
				return false;
			}
			if (this.languageCode != user.languageCode) {
				return false;
			}
			if (this.addedToAttachmentMenu != user.addedToAttachmentMenu) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.id);
			result = result * 31 + (this.firstName == null ? 0 : this.firstName.hashCode());
			result = result * 31 + (this.lastName == null ? 0 : this.lastName.hashCode());
			result = result * 31 + (this.usernames == null ? 0 : this.usernames.hashCode());
			result = result * 31 + (this.phoneNumber == null ? 0 : this.phoneNumber.hashCode());
			result = result * 31 + (this.status == null ? 0 : this.status.hashCode());
			result = result * 31 + (this.profilePhoto == null ? 0 : this.profilePhoto.hashCode());
			result = result * 31 + (this.emojiStatus == null ? 0 : this.emojiStatus.hashCode());
			result = result * 31 + (this.restrictionReason == null ? 0 : this.restrictionReason.hashCode());
			result = result * 31 + (this.type == null ? 0 : this.type.hashCode());
			result = result * 31 + (this.languageCode == null ? 0 : this.languageCode.hashCode());
			return result;
		}
	}

	/**
	 * Contains full information about a user.
	**/
	public static final class UserFullInfo extends Object {


		/**
		 * User profile photo set by the current user for the contact; may be null. If null and user.profilePhoto is null, then the photo is empty; otherwise, it is unknown. If non-null, then it is the same photo as in user.profilePhoto and chat.photo. This photo isn&#039;t returned in the list of user photos.
		**/
		public ChatPhoto personalPhoto;

		/**
		 * User profile photo; may be null. If null and user.profilePhoto is null, then the photo is empty; otherwise, it is unknown. If non-null and personalPhoto is null, then it is the same photo as in user.profilePhoto and chat.photo.
		**/
		public ChatPhoto photo;

		/**
		 * User profile photo visible if the main photo is hidden by privacy settings; may be null. If null and user.profilePhoto is null, then the photo is empty; otherwise, it is unknown. If non-null and both photo and personalPhoto are null, then it is the same photo as in user.profilePhoto and chat.photo. This photo isn&#039;t returned in the list of user photos.
		**/
		public ChatPhoto publicPhoto;

		/**
		 * True, if the user is blocked by the current user.
		**/
		public boolean isBlocked;

		/**
		 * True, if the user can be called.
		**/
		public boolean canBeCalled;

		/**
		 * True, if a video call can be created with the user.
		**/
		public boolean supportsVideoCalls;

		/**
		 * True, if the user can&#039;t be called due to their privacy settings.
		**/
		public boolean hasPrivateCalls;

		/**
		 * True, if the user can&#039;t be linked in forwarded messages due to their privacy settings.
		**/
		public boolean hasPrivateForwards;

		/**
		 * True, if voice and video notes can&#039;t be sent or forwarded to the user.
		**/
		public boolean hasRestrictedVoiceAndVideoNoteMessages;

		/**
		 * True, if the current user needs to explicitly allow to share their phone number with the user when the method addContact is used.
		**/
		public boolean needPhoneNumberPrivacyException;

		/**
		 * A short user bio; may be null for bots.
		**/
		public FormattedText bio;

		/**
		 * The list of available options for gifting Telegram Premium to the user.
		**/
		public PremiumPaymentOption[] premiumGiftOptions;

		/**
		 * Number of group chats where both the other user and the current user are a member; 0 for the current user.
		**/
		public int groupInCommonCount;

		/**
		 * For bots, information about the bot; may be null.
		**/
		public BotInfo botInfo;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -954933181;

		/**
		 * Contains full information about a user.
		**/
		public UserFullInfo() {}

		/**
		 * Contains full information about a user.
		 *
		 * @param personalPhoto User profile photo set by the current user for the contact; may be null. If null and user.profilePhoto is null, then the photo is empty; otherwise, it is unknown. If non-null, then it is the same photo as in user.profilePhoto and chat.photo. This photo isn&#039;t returned in the list of user photos.
		 * @param photo User profile photo; may be null. If null and user.profilePhoto is null, then the photo is empty; otherwise, it is unknown. If non-null and personalPhoto is null, then it is the same photo as in user.profilePhoto and chat.photo.
		 * @param publicPhoto User profile photo visible if the main photo is hidden by privacy settings; may be null. If null and user.profilePhoto is null, then the photo is empty; otherwise, it is unknown. If non-null and both photo and personalPhoto are null, then it is the same photo as in user.profilePhoto and chat.photo. This photo isn&#039;t returned in the list of user photos.
		 * @param isBlocked True, if the user is blocked by the current user.
		 * @param canBeCalled True, if the user can be called.
		 * @param supportsVideoCalls True, if a video call can be created with the user.
		 * @param hasPrivateCalls True, if the user can&#039;t be called due to their privacy settings.
		 * @param hasPrivateForwards True, if the user can&#039;t be linked in forwarded messages due to their privacy settings.
		 * @param hasRestrictedVoiceAndVideoNoteMessages True, if voice and video notes can&#039;t be sent or forwarded to the user.
		 * @param needPhoneNumberPrivacyException True, if the current user needs to explicitly allow to share their phone number with the user when the method addContact is used.
		 * @param bio A short user bio; may be null for bots.
		 * @param premiumGiftOptions The list of available options for gifting Telegram Premium to the user.
		 * @param groupInCommonCount Number of group chats where both the other user and the current user are a member; 0 for the current user.
		 * @param botInfo For bots, information about the bot; may be null.
		**/
		public UserFullInfo(ChatPhoto personalPhoto,
				ChatPhoto photo,
				ChatPhoto publicPhoto,
				boolean isBlocked,
				boolean canBeCalled,
				boolean supportsVideoCalls,
				boolean hasPrivateCalls,
				boolean hasPrivateForwards,
				boolean hasRestrictedVoiceAndVideoNoteMessages,
				boolean needPhoneNumberPrivacyException,
				FormattedText bio,
				PremiumPaymentOption[] premiumGiftOptions,
				int groupInCommonCount,
				BotInfo botInfo) {
			this.personalPhoto = personalPhoto;
			this.photo = photo;
			this.publicPhoto = publicPhoto;
			this.isBlocked = isBlocked;
			this.canBeCalled = canBeCalled;
			this.supportsVideoCalls = supportsVideoCalls;
			this.hasPrivateCalls = hasPrivateCalls;
			this.hasPrivateForwards = hasPrivateForwards;
			this.hasRestrictedVoiceAndVideoNoteMessages = hasRestrictedVoiceAndVideoNoteMessages;
			this.needPhoneNumberPrivacyException = needPhoneNumberPrivacyException;
			this.bio = bio;
			this.premiumGiftOptions = premiumGiftOptions;
			this.groupInCommonCount = groupInCommonCount;
			this.botInfo = botInfo;
		}

		/**
		 * Contains full information about a user.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UserFullInfo(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (ChatPhoto.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.personalPhoto = new ChatPhoto(input);
			}
			if (input.readBoolean()) {
				if (ChatPhoto.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.photo = new ChatPhoto(input);
			}
			if (input.readBoolean()) {
				if (ChatPhoto.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.publicPhoto = new ChatPhoto(input);
			}
			this.isBlocked = input.readBoolean();
			this.canBeCalled = input.readBoolean();
			this.supportsVideoCalls = input.readBoolean();
			this.hasPrivateCalls = input.readBoolean();
			this.hasPrivateForwards = input.readBoolean();
			this.hasRestrictedVoiceAndVideoNoteMessages = input.readBoolean();
			this.needPhoneNumberPrivacyException = input.readBoolean();
			if (input.readBoolean()) {
				if (FormattedText.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.bio = new FormattedText(input);
			}
			if (input.readBoolean()) {
				this.premiumGiftOptions = new PremiumPaymentOption[input.readInt()];
				for (int i = 0; i < this.premiumGiftOptions.length; i++) {
					if (PremiumPaymentOption.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.premiumGiftOptions[i] = new PremiumPaymentOption(input);
				}
			}
			this.groupInCommonCount = input.readInt();
			if (input.readBoolean()) {
				if (BotInfo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.botInfo = new BotInfo(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UserFullInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UserFullInfo.CONSTRUCTOR);
			if (this.personalPhoto == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.personalPhoto.serialize(output);
			}
			if (this.photo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.photo.serialize(output);
			}
			if (this.publicPhoto == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.publicPhoto.serialize(output);
			}
			output.writeBoolean(this.isBlocked);
			output.writeBoolean(this.canBeCalled);
			output.writeBoolean(this.supportsVideoCalls);
			output.writeBoolean(this.hasPrivateCalls);
			output.writeBoolean(this.hasPrivateForwards);
			output.writeBoolean(this.hasRestrictedVoiceAndVideoNoteMessages);
			output.writeBoolean(this.needPhoneNumberPrivacyException);
			if (this.bio == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.bio.serialize(output);
			}
			if (this.premiumGiftOptions == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.premiumGiftOptions.length);
				for (int i = 0; i < this.premiumGiftOptions.length; i++) {
					this.premiumGiftOptions[i].serialize(output);
				}
			}
			output.writeInt(this.groupInCommonCount);
			if (this.botInfo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.botInfo.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UserFullInfo userFullInfo = (UserFullInfo) o;
			if (!Objects.equals(this.personalPhoto, userFullInfo.personalPhoto)) {
				return false;
			}
			if (!Objects.equals(this.photo, userFullInfo.photo)) {
				return false;
			}
			if (!Objects.equals(this.publicPhoto, userFullInfo.publicPhoto)) {
				return false;
			}
			if (this.isBlocked != userFullInfo.isBlocked) {
				return false;
			}
			if (this.canBeCalled != userFullInfo.canBeCalled) {
				return false;
			}
			if (this.supportsVideoCalls != userFullInfo.supportsVideoCalls) {
				return false;
			}
			if (this.hasPrivateCalls != userFullInfo.hasPrivateCalls) {
				return false;
			}
			if (this.hasPrivateForwards != userFullInfo.hasPrivateForwards) {
				return false;
			}
			if (this.hasRestrictedVoiceAndVideoNoteMessages != userFullInfo.hasRestrictedVoiceAndVideoNoteMessages) {
				return false;
			}
			if (this.needPhoneNumberPrivacyException != userFullInfo.needPhoneNumberPrivacyException) {
				return false;
			}
			if (!Objects.equals(this.bio, userFullInfo.bio)) {
				return false;
			}
			if (!Arrays.equals(this.premiumGiftOptions, userFullInfo.premiumGiftOptions)) {
				return false;
			}
			if (this.groupInCommonCount != userFullInfo.groupInCommonCount) {
				return false;
			}
			if (!Objects.equals(this.botInfo, userFullInfo.botInfo)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isBlocked);
			result = result * 31 + (this.personalPhoto == null ? 0 : this.personalPhoto.hashCode());
			result = result * 31 + (this.photo == null ? 0 : this.photo.hashCode());
			result = result * 31 + (this.publicPhoto == null ? 0 : this.publicPhoto.hashCode());
			result = result * 31 + (this.bio == null ? 0 : this.bio.hashCode());
			result = result * 31 + (Arrays.hashCode(this.premiumGiftOptions));
			result = result * 31 + (this.botInfo == null ? 0 : this.botInfo.hashCode());
			return result;
		}
	}

	/**
	 * Contains an HTTPS URL, which can be used to get information about a
	 * user.
	**/
	public static final class UserLink extends Object {


		/**
		 * The URL.
		**/
		public String url;

		/**
		 * Left time for which the link is valid, in seconds; 0 if the link is a public username link.
		**/
		public int expiresIn;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 498138872;

		/**
		 * Contains an HTTPS URL, which can be used to get information about a user.
		**/
		public UserLink() {}

		/**
		 * Contains an HTTPS URL, which can be used to get information about a user.
		 *
		 * @param url The URL.
		 * @param expiresIn Left time for which the link is valid, in seconds; 0 if the link is a public username link.
		**/
		public UserLink(String url, int expiresIn) {
			this.url = url;
			this.expiresIn = expiresIn;
		}

		/**
		 * Contains an HTTPS URL, which can be used to get information about a user.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UserLink(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] urlTmp = new byte[input.readInt()];
				input.readFully(urlTmp);
				this.url = new String(urlTmp, StandardCharsets.UTF_8);
			}
			this.expiresIn = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UserLink.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UserLink.CONSTRUCTOR);
			if (this.url == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] urlTmp = this.url.getBytes(StandardCharsets.UTF_8);
				output.writeInt(urlTmp.length);
				output.write(urlTmp);
			}
			output.writeInt(this.expiresIn);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UserLink userLink = (UserLink) o;
			if (this.url != userLink.url) {
				return false;
			}
			if (this.expiresIn != userLink.expiresIn) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.expiresIn);
			result = result * 31 + (this.url == null ? 0 : this.url.hashCode());
			return result;
		}
	}

	/**
	 * A privacy setting for managing whether the user&#039;s online status
	 * is visible.
	**/
	public static final class UserPrivacySettingShowStatus extends UserPrivacySetting {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1862829310;

		/**
		 * A privacy setting for managing whether the user&#039;s online status is visible.
		**/
		public UserPrivacySettingShowStatus() {}

		/**
		 * A privacy setting for managing whether the user&#039;s online status is visible.
		 *
		**/

		/**
		 * A privacy setting for managing whether the user&#039;s online status is visible.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UserPrivacySettingShowStatus(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UserPrivacySettingShowStatus.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UserPrivacySettingShowStatus.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return UserPrivacySettingShowStatus.CONSTRUCTOR;
		}
	}

	/**
	 * A privacy setting for managing whether the user&#039;s profile photo
	 * is visible.
	**/
	public static final class UserPrivacySettingShowProfilePhoto extends UserPrivacySetting {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1408485877;

		/**
		 * A privacy setting for managing whether the user&#039;s profile photo is visible.
		**/
		public UserPrivacySettingShowProfilePhoto() {}

		/**
		 * A privacy setting for managing whether the user&#039;s profile photo is visible.
		 *
		**/

		/**
		 * A privacy setting for managing whether the user&#039;s profile photo is visible.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UserPrivacySettingShowProfilePhoto(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UserPrivacySettingShowProfilePhoto.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UserPrivacySettingShowProfilePhoto.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return UserPrivacySettingShowProfilePhoto.CONSTRUCTOR;
		}
	}

	/**
	 * A privacy setting for managing whether a link to the user&#039;s
	 * account is included in forwarded messages.
	**/
	public static final class UserPrivacySettingShowLinkInForwardedMessages extends UserPrivacySetting {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 592688870;

		/**
		 * A privacy setting for managing whether a link to the user&#039;s account is included in forwarded messages.
		**/
		public UserPrivacySettingShowLinkInForwardedMessages() {}

		/**
		 * A privacy setting for managing whether a link to the user&#039;s account is included in forwarded messages.
		 *
		**/

		/**
		 * A privacy setting for managing whether a link to the user&#039;s account is included in forwarded messages.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UserPrivacySettingShowLinkInForwardedMessages(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UserPrivacySettingShowLinkInForwardedMessages.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UserPrivacySettingShowLinkInForwardedMessages.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return UserPrivacySettingShowLinkInForwardedMessages.CONSTRUCTOR;
		}
	}

	/**
	 * A privacy setting for managing whether the user&#039;s phone number
	 * is visible.
	**/
	public static final class UserPrivacySettingShowPhoneNumber extends UserPrivacySetting {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -791567831;

		/**
		 * A privacy setting for managing whether the user&#039;s phone number is visible.
		**/
		public UserPrivacySettingShowPhoneNumber() {}

		/**
		 * A privacy setting for managing whether the user&#039;s phone number is visible.
		 *
		**/

		/**
		 * A privacy setting for managing whether the user&#039;s phone number is visible.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UserPrivacySettingShowPhoneNumber(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UserPrivacySettingShowPhoneNumber.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UserPrivacySettingShowPhoneNumber.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return UserPrivacySettingShowPhoneNumber.CONSTRUCTOR;
		}
	}

	/**
	 * A privacy setting for managing whether the user can be invited to
	 * chats.
	**/
	public static final class UserPrivacySettingAllowChatInvites extends UserPrivacySetting {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1271668007;

		/**
		 * A privacy setting for managing whether the user can be invited to chats.
		**/
		public UserPrivacySettingAllowChatInvites() {}

		/**
		 * A privacy setting for managing whether the user can be invited to chats.
		 *
		**/

		/**
		 * A privacy setting for managing whether the user can be invited to chats.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UserPrivacySettingAllowChatInvites(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UserPrivacySettingAllowChatInvites.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UserPrivacySettingAllowChatInvites.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return UserPrivacySettingAllowChatInvites.CONSTRUCTOR;
		}
	}

	/**
	 * A privacy setting for managing whether the user can be called.
	**/
	public static final class UserPrivacySettingAllowCalls extends UserPrivacySetting {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -906967291;

		/**
		 * A privacy setting for managing whether the user can be called.
		**/
		public UserPrivacySettingAllowCalls() {}

		/**
		 * A privacy setting for managing whether the user can be called.
		 *
		**/

		/**
		 * A privacy setting for managing whether the user can be called.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UserPrivacySettingAllowCalls(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UserPrivacySettingAllowCalls.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UserPrivacySettingAllowCalls.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return UserPrivacySettingAllowCalls.CONSTRUCTOR;
		}
	}

	/**
	 * A privacy setting for managing whether peer-to-peer connections can
	 * be used for calls.
	**/
	public static final class UserPrivacySettingAllowPeerToPeerCalls extends UserPrivacySetting {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 352500032;

		/**
		 * A privacy setting for managing whether peer-to-peer connections can be used for calls.
		**/
		public UserPrivacySettingAllowPeerToPeerCalls() {}

		/**
		 * A privacy setting for managing whether peer-to-peer connections can be used for calls.
		 *
		**/

		/**
		 * A privacy setting for managing whether peer-to-peer connections can be used for calls.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UserPrivacySettingAllowPeerToPeerCalls(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UserPrivacySettingAllowPeerToPeerCalls.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UserPrivacySettingAllowPeerToPeerCalls.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return UserPrivacySettingAllowPeerToPeerCalls.CONSTRUCTOR;
		}
	}

	/**
	 * A privacy setting for managing whether the user can be found by their
	 * phone number. Checked only if the phone number is not known to the
	 * other user. Can be set only to &quot;Allow contacts&quot; or
	 * &quot;Allow all&quot;.
	**/
	public static final class UserPrivacySettingAllowFindingByPhoneNumber extends UserPrivacySetting {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1846645423;

		/**
		 * A privacy setting for managing whether the user can be found by their phone number. Checked only if the phone number is not known to the other user. Can be set only to &quot;Allow contacts&quot; or &quot;Allow all&quot;.
		**/
		public UserPrivacySettingAllowFindingByPhoneNumber() {}

		/**
		 * A privacy setting for managing whether the user can be found by their phone number. Checked only if the phone number is not known to the other user. Can be set only to &quot;Allow contacts&quot; or &quot;Allow all&quot;.
		 *
		**/

		/**
		 * A privacy setting for managing whether the user can be found by their phone number. Checked only if the phone number is not known to the other user. Can be set only to &quot;Allow contacts&quot; or &quot;Allow all&quot;.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UserPrivacySettingAllowFindingByPhoneNumber(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UserPrivacySettingAllowFindingByPhoneNumber.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UserPrivacySettingAllowFindingByPhoneNumber.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return UserPrivacySettingAllowFindingByPhoneNumber.CONSTRUCTOR;
		}
	}

	/**
	 * A privacy setting for managing whether the user can receive voice and
	 * video messages in private chats.
	**/
	public static final class UserPrivacySettingAllowPrivateVoiceAndVideoNoteMessages extends UserPrivacySetting {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 338112060;

		/**
		 * A privacy setting for managing whether the user can receive voice and video messages in private chats.
		**/
		public UserPrivacySettingAllowPrivateVoiceAndVideoNoteMessages() {}

		/**
		 * A privacy setting for managing whether the user can receive voice and video messages in private chats.
		 *
		**/

		/**
		 * A privacy setting for managing whether the user can receive voice and video messages in private chats.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UserPrivacySettingAllowPrivateVoiceAndVideoNoteMessages(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UserPrivacySettingAllowPrivateVoiceAndVideoNoteMessages.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UserPrivacySettingAllowPrivateVoiceAndVideoNoteMessages.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return UserPrivacySettingAllowPrivateVoiceAndVideoNoteMessages.CONSTRUCTOR;
		}
	}

	/**
	 * A rule to allow all users to do something.
	**/
	public static final class UserPrivacySettingRuleAllowAll extends UserPrivacySettingRule {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1967186881;

		/**
		 * A rule to allow all users to do something.
		**/
		public UserPrivacySettingRuleAllowAll() {}

		/**
		 * A rule to allow all users to do something.
		 *
		**/

		/**
		 * A rule to allow all users to do something.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UserPrivacySettingRuleAllowAll(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UserPrivacySettingRuleAllowAll.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UserPrivacySettingRuleAllowAll.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return UserPrivacySettingRuleAllowAll.CONSTRUCTOR;
		}
	}

	/**
	 * A rule to allow all of a user&#039;s contacts to do something.
	**/
	public static final class UserPrivacySettingRuleAllowContacts extends UserPrivacySettingRule {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1892733680;

		/**
		 * A rule to allow all of a user&#039;s contacts to do something.
		**/
		public UserPrivacySettingRuleAllowContacts() {}

		/**
		 * A rule to allow all of a user&#039;s contacts to do something.
		 *
		**/

		/**
		 * A rule to allow all of a user&#039;s contacts to do something.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UserPrivacySettingRuleAllowContacts(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UserPrivacySettingRuleAllowContacts.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UserPrivacySettingRuleAllowContacts.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return UserPrivacySettingRuleAllowContacts.CONSTRUCTOR;
		}
	}

	/**
	 * A rule to allow certain specified users to do something.
	**/
	public static final class UserPrivacySettingRuleAllowUsers extends UserPrivacySettingRule {


		/**
		 * The user identifiers, total number of users in all rules must not exceed 1000.
		**/
		public long[] userIds;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1110988334;

		/**
		 * A rule to allow certain specified users to do something.
		**/
		public UserPrivacySettingRuleAllowUsers() {}

		/**
		 * A rule to allow certain specified users to do something.
		 *
		 * @param userIds The user identifiers, total number of users in all rules must not exceed 1000.
		**/
		public UserPrivacySettingRuleAllowUsers(long[] userIds) {
			this.userIds = userIds;
		}

		/**
		 * A rule to allow certain specified users to do something.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UserPrivacySettingRuleAllowUsers(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.userIds = new long[input.readInt()];
				for (int i = 0; i < this.userIds.length; i++) {
					this.userIds[i] = input.readLong();
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UserPrivacySettingRuleAllowUsers.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UserPrivacySettingRuleAllowUsers.CONSTRUCTOR);
			if (this.userIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.userIds.length);
				for (int i = 0; i < this.userIds.length; i++) {
					output.writeLong(this.userIds[i]);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UserPrivacySettingRuleAllowUsers userPrivacySettingRuleAllowUsers = (UserPrivacySettingRuleAllowUsers) o;
			if (!Arrays.equals(this.userIds, userPrivacySettingRuleAllowUsers.userIds)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.userIds);
		}
	}

	/**
	 * A rule to allow all members of certain specified basic groups and
	 * supergroups to doing something.
	**/
	public static final class UserPrivacySettingRuleAllowChatMembers extends UserPrivacySettingRule {


		/**
		 * The chat identifiers, total number of chats in all rules must not exceed 20.
		**/
		public long[] chatIds;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2048749863;

		/**
		 * A rule to allow all members of certain specified basic groups and supergroups to doing something.
		**/
		public UserPrivacySettingRuleAllowChatMembers() {}

		/**
		 * A rule to allow all members of certain specified basic groups and supergroups to doing something.
		 *
		 * @param chatIds The chat identifiers, total number of chats in all rules must not exceed 20.
		**/
		public UserPrivacySettingRuleAllowChatMembers(long[] chatIds) {
			this.chatIds = chatIds;
		}

		/**
		 * A rule to allow all members of certain specified basic groups and supergroups to doing something.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UserPrivacySettingRuleAllowChatMembers(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.chatIds = new long[input.readInt()];
				for (int i = 0; i < this.chatIds.length; i++) {
					this.chatIds[i] = input.readLong();
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UserPrivacySettingRuleAllowChatMembers.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UserPrivacySettingRuleAllowChatMembers.CONSTRUCTOR);
			if (this.chatIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.chatIds.length);
				for (int i = 0; i < this.chatIds.length; i++) {
					output.writeLong(this.chatIds[i]);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UserPrivacySettingRuleAllowChatMembers userPrivacySettingRuleAllowChatMembers = (UserPrivacySettingRuleAllowChatMembers) o;
			if (!Arrays.equals(this.chatIds, userPrivacySettingRuleAllowChatMembers.chatIds)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.chatIds);
		}
	}

	/**
	 * A rule to restrict all users from doing something.
	**/
	public static final class UserPrivacySettingRuleRestrictAll extends UserPrivacySettingRule {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1406495408;

		/**
		 * A rule to restrict all users from doing something.
		**/
		public UserPrivacySettingRuleRestrictAll() {}

		/**
		 * A rule to restrict all users from doing something.
		 *
		**/

		/**
		 * A rule to restrict all users from doing something.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UserPrivacySettingRuleRestrictAll(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UserPrivacySettingRuleRestrictAll.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UserPrivacySettingRuleRestrictAll.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return UserPrivacySettingRuleRestrictAll.CONSTRUCTOR;
		}
	}

	/**
	 * A rule to restrict all contacts of a user from doing something.
	**/
	public static final class UserPrivacySettingRuleRestrictContacts extends UserPrivacySettingRule {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1008389378;

		/**
		 * A rule to restrict all contacts of a user from doing something.
		**/
		public UserPrivacySettingRuleRestrictContacts() {}

		/**
		 * A rule to restrict all contacts of a user from doing something.
		 *
		**/

		/**
		 * A rule to restrict all contacts of a user from doing something.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UserPrivacySettingRuleRestrictContacts(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UserPrivacySettingRuleRestrictContacts.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UserPrivacySettingRuleRestrictContacts.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return UserPrivacySettingRuleRestrictContacts.CONSTRUCTOR;
		}
	}

	/**
	 * A rule to restrict all specified users from doing something.
	**/
	public static final class UserPrivacySettingRuleRestrictUsers extends UserPrivacySettingRule {


		/**
		 * The user identifiers, total number of users in all rules must not exceed 1000.
		**/
		public long[] userIds;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 622796522;

		/**
		 * A rule to restrict all specified users from doing something.
		**/
		public UserPrivacySettingRuleRestrictUsers() {}

		/**
		 * A rule to restrict all specified users from doing something.
		 *
		 * @param userIds The user identifiers, total number of users in all rules must not exceed 1000.
		**/
		public UserPrivacySettingRuleRestrictUsers(long[] userIds) {
			this.userIds = userIds;
		}

		/**
		 * A rule to restrict all specified users from doing something.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UserPrivacySettingRuleRestrictUsers(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.userIds = new long[input.readInt()];
				for (int i = 0; i < this.userIds.length; i++) {
					this.userIds[i] = input.readLong();
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UserPrivacySettingRuleRestrictUsers.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UserPrivacySettingRuleRestrictUsers.CONSTRUCTOR);
			if (this.userIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.userIds.length);
				for (int i = 0; i < this.userIds.length; i++) {
					output.writeLong(this.userIds[i]);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UserPrivacySettingRuleRestrictUsers userPrivacySettingRuleRestrictUsers = (UserPrivacySettingRuleRestrictUsers) o;
			if (!Arrays.equals(this.userIds, userPrivacySettingRuleRestrictUsers.userIds)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.userIds);
		}
	}

	/**
	 * A rule to restrict all members of specified basic groups and
	 * supergroups from doing something.
	**/
	public static final class UserPrivacySettingRuleRestrictChatMembers extends UserPrivacySettingRule {


		/**
		 * The chat identifiers, total number of chats in all rules must not exceed 20.
		**/
		public long[] chatIds;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 392530897;

		/**
		 * A rule to restrict all members of specified basic groups and supergroups from doing something.
		**/
		public UserPrivacySettingRuleRestrictChatMembers() {}

		/**
		 * A rule to restrict all members of specified basic groups and supergroups from doing something.
		 *
		 * @param chatIds The chat identifiers, total number of chats in all rules must not exceed 20.
		**/
		public UserPrivacySettingRuleRestrictChatMembers(long[] chatIds) {
			this.chatIds = chatIds;
		}

		/**
		 * A rule to restrict all members of specified basic groups and supergroups from doing something.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UserPrivacySettingRuleRestrictChatMembers(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.chatIds = new long[input.readInt()];
				for (int i = 0; i < this.chatIds.length; i++) {
					this.chatIds[i] = input.readLong();
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UserPrivacySettingRuleRestrictChatMembers.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UserPrivacySettingRuleRestrictChatMembers.CONSTRUCTOR);
			if (this.chatIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.chatIds.length);
				for (int i = 0; i < this.chatIds.length; i++) {
					output.writeLong(this.chatIds[i]);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UserPrivacySettingRuleRestrictChatMembers userPrivacySettingRuleRestrictChatMembers = (UserPrivacySettingRuleRestrictChatMembers) o;
			if (!Arrays.equals(this.chatIds, userPrivacySettingRuleRestrictChatMembers.chatIds)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.chatIds);
		}
	}

	/**
	 * A list of privacy rules. Rules are matched in the specified order.
	 * The first matched rule defines the privacy setting for a given user.
	 * If no rule matches, the action is not allowed.
	**/
	public static final class UserPrivacySettingRules extends Object {


		/**
		 * A list of rules.
		**/
		public UserPrivacySettingRule[] rules;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 322477541;

		/**
		 * A list of privacy rules. Rules are matched in the specified order. The first matched rule defines the privacy setting for a given user. If no rule matches, the action is not allowed.
		**/
		public UserPrivacySettingRules() {}

		/**
		 * A list of privacy rules. Rules are matched in the specified order. The first matched rule defines the privacy setting for a given user. If no rule matches, the action is not allowed.
		 *
		 * @param rules A list of rules.
		**/
		public UserPrivacySettingRules(UserPrivacySettingRule[] rules) {
			this.rules = rules;
		}

		/**
		 * A list of privacy rules. Rules are matched in the specified order. The first matched rule defines the privacy setting for a given user. If no rule matches, the action is not allowed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UserPrivacySettingRules(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.rules = new UserPrivacySettingRule[input.readInt()];
				for (int i = 0; i < this.rules.length; i++) {
					switch(input.readInt()) {
						case UserPrivacySettingRuleAllowAll.CONSTRUCTOR: this.rules[i] = new UserPrivacySettingRuleAllowAll(input); break;
						case UserPrivacySettingRuleAllowContacts.CONSTRUCTOR: this.rules[i] = new UserPrivacySettingRuleAllowContacts(input); break;
						case UserPrivacySettingRuleAllowUsers.CONSTRUCTOR: this.rules[i] = new UserPrivacySettingRuleAllowUsers(input); break;
						case UserPrivacySettingRuleAllowChatMembers.CONSTRUCTOR: this.rules[i] = new UserPrivacySettingRuleAllowChatMembers(input); break;
						case UserPrivacySettingRuleRestrictAll.CONSTRUCTOR: this.rules[i] = new UserPrivacySettingRuleRestrictAll(input); break;
						case UserPrivacySettingRuleRestrictContacts.CONSTRUCTOR: this.rules[i] = new UserPrivacySettingRuleRestrictContacts(input); break;
						case UserPrivacySettingRuleRestrictUsers.CONSTRUCTOR: this.rules[i] = new UserPrivacySettingRuleRestrictUsers(input); break;
						case UserPrivacySettingRuleRestrictChatMembers.CONSTRUCTOR: this.rules[i] = new UserPrivacySettingRuleRestrictChatMembers(input); break;
						default: {
							throw new UnsupportedOperationException();
						}
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UserPrivacySettingRules.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UserPrivacySettingRules.CONSTRUCTOR);
			if (this.rules == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.rules.length);
				for (int i = 0; i < this.rules.length; i++) {
					this.rules[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UserPrivacySettingRules userPrivacySettingRules = (UserPrivacySettingRules) o;
			if (!Arrays.equals(this.rules, userPrivacySettingRules.rules)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.rules);
		}
	}

	/**
	 * The user status was never changed.
	**/
	public static final class UserStatusEmpty extends UserStatus {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 164646985;

		/**
		 * The user status was never changed.
		**/
		public UserStatusEmpty() {}

		/**
		 * The user status was never changed.
		 *
		**/

		/**
		 * The user status was never changed.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UserStatusEmpty(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UserStatusEmpty.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UserStatusEmpty.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return UserStatusEmpty.CONSTRUCTOR;
		}
	}

	/**
	 * The user is online.
	**/
	public static final class UserStatusOnline extends UserStatus {


		/**
		 * Point in time (Unix timestamp) when the user&#039;s online status will expire.
		**/
		public int expires;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1529460876;

		/**
		 * The user is online.
		**/
		public UserStatusOnline() {}

		/**
		 * The user is online.
		 *
		 * @param expires Point in time (Unix timestamp) when the user&#039;s online status will expire.
		**/
		public UserStatusOnline(int expires) {
			this.expires = expires;
		}

		/**
		 * The user is online.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UserStatusOnline(DataInput input) throws IOException {
			this.expires = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UserStatusOnline.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UserStatusOnline.CONSTRUCTOR);
			output.writeInt(this.expires);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UserStatusOnline userStatusOnline = (UserStatusOnline) o;
			if (this.expires != userStatusOnline.expires) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.expires);
		}
	}

	/**
	 * The user is offline.
	**/
	public static final class UserStatusOffline extends UserStatus {


		/**
		 * Point in time (Unix timestamp) when the user was last online.
		**/
		public int wasOnline;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -759984891;

		/**
		 * The user is offline.
		**/
		public UserStatusOffline() {}

		/**
		 * The user is offline.
		 *
		 * @param wasOnline Point in time (Unix timestamp) when the user was last online.
		**/
		public UserStatusOffline(int wasOnline) {
			this.wasOnline = wasOnline;
		}

		/**
		 * The user is offline.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UserStatusOffline(DataInput input) throws IOException {
			this.wasOnline = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UserStatusOffline.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UserStatusOffline.CONSTRUCTOR);
			output.writeInt(this.wasOnline);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UserStatusOffline userStatusOffline = (UserStatusOffline) o;
			if (this.wasOnline != userStatusOffline.wasOnline) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.wasOnline);
		}
	}

	/**
	 * The user was online recently.
	**/
	public static final class UserStatusRecently extends UserStatus {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -496024847;

		/**
		 * The user was online recently.
		**/
		public UserStatusRecently() {}

		/**
		 * The user was online recently.
		 *
		**/

		/**
		 * The user was online recently.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UserStatusRecently(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UserStatusRecently.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UserStatusRecently.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return UserStatusRecently.CONSTRUCTOR;
		}
	}

	/**
	 * The user is offline, but was online last week.
	**/
	public static final class UserStatusLastWeek extends UserStatus {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 129960444;

		/**
		 * The user is offline, but was online last week.
		**/
		public UserStatusLastWeek() {}

		/**
		 * The user is offline, but was online last week.
		 *
		**/

		/**
		 * The user is offline, but was online last week.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UserStatusLastWeek(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UserStatusLastWeek.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UserStatusLastWeek.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return UserStatusLastWeek.CONSTRUCTOR;
		}
	}

	/**
	 * The user is offline, but was online last month.
	**/
	public static final class UserStatusLastMonth extends UserStatus {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2011940674;

		/**
		 * The user is offline, but was online last month.
		**/
		public UserStatusLastMonth() {}

		/**
		 * The user is offline, but was online last month.
		 *
		**/

		/**
		 * The user is offline, but was online last month.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UserStatusLastMonth(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UserStatusLastMonth.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UserStatusLastMonth.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return UserStatusLastMonth.CONSTRUCTOR;
		}
	}

	/**
	 * Contains custom information about the user.
	**/
	public static final class UserSupportInfo extends Object {


		/**
		 * Information message.
		**/
		public FormattedText message;

		/**
		 * Information author.
		**/
		public String author;

		/**
		 * Information change date.
		**/
		public int date;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1257366487;

		/**
		 * Contains custom information about the user.
		**/
		public UserSupportInfo() {}

		/**
		 * Contains custom information about the user.
		 *
		 * @param message Information message.
		 * @param author Information author.
		 * @param date Information change date.
		**/
		public UserSupportInfo(FormattedText message, String author, int date) {
			this.message = message;
			this.author = author;
			this.date = date;
		}

		/**
		 * Contains custom information about the user.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UserSupportInfo(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (FormattedText.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.message = new FormattedText(input);
			}
			if (input.readBoolean()) {
				byte[] authorTmp = new byte[input.readInt()];
				input.readFully(authorTmp);
				this.author = new String(authorTmp, StandardCharsets.UTF_8);
			}
			this.date = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UserSupportInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UserSupportInfo.CONSTRUCTOR);
			if (this.message == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.message.serialize(output);
			}
			if (this.author == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] authorTmp = this.author.getBytes(StandardCharsets.UTF_8);
				output.writeInt(authorTmp.length);
				output.write(authorTmp);
			}
			output.writeInt(this.date);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UserSupportInfo userSupportInfo = (UserSupportInfo) o;
			if (!Objects.equals(this.message, userSupportInfo.message)) {
				return false;
			}
			if (this.author != userSupportInfo.author) {
				return false;
			}
			if (this.date != userSupportInfo.date) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.date);
			result = result * 31 + (this.message == null ? 0 : this.message.hashCode());
			result = result * 31 + (this.author == null ? 0 : this.author.hashCode());
			return result;
		}
	}

	/**
	 * A regular user.
	**/
	public static final class UserTypeRegular extends UserType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -598644325;

		/**
		 * A regular user.
		**/
		public UserTypeRegular() {}

		/**
		 * A regular user.
		 *
		**/

		/**
		 * A regular user.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UserTypeRegular(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UserTypeRegular.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UserTypeRegular.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return UserTypeRegular.CONSTRUCTOR;
		}
	}

	/**
	 * A deleted user or deleted bot. No information on the user besides the
	 * user identifier is available. It is not possible to perform any
	 * active actions on this type of user.
	**/
	public static final class UserTypeDeleted extends UserType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1807729372;

		/**
		 * A deleted user or deleted bot. No information on the user besides the user identifier is available. It is not possible to perform any active actions on this type of user.
		**/
		public UserTypeDeleted() {}

		/**
		 * A deleted user or deleted bot. No information on the user besides the user identifier is available. It is not possible to perform any active actions on this type of user.
		 *
		**/

		/**
		 * A deleted user or deleted bot. No information on the user besides the user identifier is available. It is not possible to perform any active actions on this type of user.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UserTypeDeleted(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UserTypeDeleted.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UserTypeDeleted.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return UserTypeDeleted.CONSTRUCTOR;
		}
	}

	/**
	 * A bot (see https://core.telegram.org/bots).
	**/
	public static final class UserTypeBot extends UserType {


		/**
		 * True, if the bot is owned by the current user and can be edited using the methods toggleBotUsernameIsActive, reorderBotActiveUsernames, setBotProfilePhoto, setBotName, setBotInfoDescription, and setBotInfoShortDescription.
		**/
		public boolean canBeEdited;

		/**
		 * True, if the bot can be invited to basic group and supergroup chats.
		**/
		public boolean canJoinGroups;

		/**
		 * True, if the bot can read all messages in basic group or supergroup chats and not just those addressed to the bot. In private and channel chats a bot can always read all messages.
		**/
		public boolean canReadAllGroupMessages;

		/**
		 * True, if the bot supports inline queries.
		**/
		public boolean isInline;

		/**
		 * Placeholder for inline queries (displayed on the application input field).
		**/
		public String inlineQueryPlaceholder;

		/**
		 * True, if the location of the user is expected to be sent with every inline query to this bot.
		**/
		public boolean needLocation;

		/**
		 * True, if the bot can be added to attachment menu.
		**/
		public boolean canBeAddedToAttachmentMenu;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -109451376;

		/**
		 * A bot (see https://core.telegram.org/bots).
		**/
		public UserTypeBot() {}

		/**
		 * A bot (see https://core.telegram.org/bots).
		 *
		 * @param canBeEdited True, if the bot is owned by the current user and can be edited using the methods toggleBotUsernameIsActive, reorderBotActiveUsernames, setBotProfilePhoto, setBotName, setBotInfoDescription, and setBotInfoShortDescription.
		 * @param canJoinGroups True, if the bot can be invited to basic group and supergroup chats.
		 * @param canReadAllGroupMessages True, if the bot can read all messages in basic group or supergroup chats and not just those addressed to the bot. In private and channel chats a bot can always read all messages.
		 * @param isInline True, if the bot supports inline queries.
		 * @param inlineQueryPlaceholder Placeholder for inline queries (displayed on the application input field).
		 * @param needLocation True, if the location of the user is expected to be sent with every inline query to this bot.
		 * @param canBeAddedToAttachmentMenu True, if the bot can be added to attachment menu.
		**/
		public UserTypeBot(boolean canBeEdited,
				boolean canJoinGroups,
				boolean canReadAllGroupMessages,
				boolean isInline,
				String inlineQueryPlaceholder,
				boolean needLocation,
				boolean canBeAddedToAttachmentMenu) {
			this.canBeEdited = canBeEdited;
			this.canJoinGroups = canJoinGroups;
			this.canReadAllGroupMessages = canReadAllGroupMessages;
			this.isInline = isInline;
			this.inlineQueryPlaceholder = inlineQueryPlaceholder;
			this.needLocation = needLocation;
			this.canBeAddedToAttachmentMenu = canBeAddedToAttachmentMenu;
		}

		/**
		 * A bot (see https://core.telegram.org/bots).
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UserTypeBot(DataInput input) throws IOException {
			this.canBeEdited = input.readBoolean();
			this.canJoinGroups = input.readBoolean();
			this.canReadAllGroupMessages = input.readBoolean();
			this.isInline = input.readBoolean();
			if (input.readBoolean()) {
				byte[] inlineQueryPlaceholderTmp = new byte[input.readInt()];
				input.readFully(inlineQueryPlaceholderTmp);
				this.inlineQueryPlaceholder = new String(inlineQueryPlaceholderTmp, StandardCharsets.UTF_8);
			}
			this.needLocation = input.readBoolean();
			this.canBeAddedToAttachmentMenu = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UserTypeBot.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UserTypeBot.CONSTRUCTOR);
			output.writeBoolean(this.canBeEdited);
			output.writeBoolean(this.canJoinGroups);
			output.writeBoolean(this.canReadAllGroupMessages);
			output.writeBoolean(this.isInline);
			if (this.inlineQueryPlaceholder == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] inlineQueryPlaceholderTmp = this.inlineQueryPlaceholder.getBytes(StandardCharsets.UTF_8);
				output.writeInt(inlineQueryPlaceholderTmp.length);
				output.write(inlineQueryPlaceholderTmp);
			}
			output.writeBoolean(this.needLocation);
			output.writeBoolean(this.canBeAddedToAttachmentMenu);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UserTypeBot userTypeBot = (UserTypeBot) o;
			if (this.canBeEdited != userTypeBot.canBeEdited) {
				return false;
			}
			if (this.canJoinGroups != userTypeBot.canJoinGroups) {
				return false;
			}
			if (this.canReadAllGroupMessages != userTypeBot.canReadAllGroupMessages) {
				return false;
			}
			if (this.isInline != userTypeBot.isInline) {
				return false;
			}
			if (this.inlineQueryPlaceholder != userTypeBot.inlineQueryPlaceholder) {
				return false;
			}
			if (this.needLocation != userTypeBot.needLocation) {
				return false;
			}
			if (this.canBeAddedToAttachmentMenu != userTypeBot.canBeAddedToAttachmentMenu) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.canBeEdited);
			result = result * 31 + (this.inlineQueryPlaceholder == null ? 0 : this.inlineQueryPlaceholder.hashCode());
			return result;
		}
	}

	/**
	 * No information on the user besides the user identifier is available,
	 * yet this user has not been deleted. This object is extremely rare and
	 * must be handled like a deleted user. It is not possible to perform
	 * any actions on users of this type.
	**/
	public static final class UserTypeUnknown extends UserType {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -724541123;

		/**
		 * No information on the user besides the user identifier is available, yet this user has not been deleted. This object is extremely rare and must be handled like a deleted user. It is not possible to perform any actions on users of this type.
		**/
		public UserTypeUnknown() {}

		/**
		 * No information on the user besides the user identifier is available, yet this user has not been deleted. This object is extremely rare and must be handled like a deleted user. It is not possible to perform any actions on users of this type.
		 *
		**/

		/**
		 * No information on the user besides the user identifier is available, yet this user has not been deleted. This object is extremely rare and must be handled like a deleted user. It is not possible to perform any actions on users of this type.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UserTypeUnknown(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UserTypeUnknown.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UserTypeUnknown.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return UserTypeUnknown.CONSTRUCTOR;
		}
	}

	/**
	 * Describes usernames assigned to a user, a supergroup, or a channel.
	**/
	public static final class Usernames extends Object {


		/**
		 * List of active usernames; the first one must be shown as the primary username. The order of active usernames can be changed with reorderActiveUsernames, reorderBotActiveUsernames or reorderSupergroupActiveUsernames.
		**/
		public String[] activeUsernames;

		/**
		 * List of currently disabled usernames; the username can be activated with toggleUsernameIsActive, toggleBotUsernameIsActive, or toggleSupergroupUsernameIsActive.
		**/
		public String[] disabledUsernames;

		/**
		 * The active username, which can be changed with setUsername or setSupergroupUsername.
		**/
		public String editableUsername;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 799608565;

		/**
		 * Describes usernames assigned to a user, a supergroup, or a channel.
		**/
		public Usernames() {}

		/**
		 * Describes usernames assigned to a user, a supergroup, or a channel.
		 *
		 * @param activeUsernames List of active usernames; the first one must be shown as the primary username. The order of active usernames can be changed with reorderActiveUsernames, reorderBotActiveUsernames or reorderSupergroupActiveUsernames.
		 * @param disabledUsernames List of currently disabled usernames; the username can be activated with toggleUsernameIsActive, toggleBotUsernameIsActive, or toggleSupergroupUsernameIsActive.
		 * @param editableUsername The active username, which can be changed with setUsername or setSupergroupUsername.
		**/
		public Usernames(String[] activeUsernames,
				String[] disabledUsernames,
				String editableUsername) {
			this.activeUsernames = activeUsernames;
			this.disabledUsernames = disabledUsernames;
			this.editableUsername = editableUsername;
		}

		/**
		 * Describes usernames assigned to a user, a supergroup, or a channel.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public Usernames(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.activeUsernames = new String[input.readInt()];
				for (int i = 0; i < this.activeUsernames.length; i++) {
					byte[] activeUsernamesTmp = new byte[input.readInt()];
					input.readFully(activeUsernamesTmp);
					this.activeUsernames[i] = new String(activeUsernamesTmp, StandardCharsets.UTF_8);
				}
			}
			if (input.readBoolean()) {
				this.disabledUsernames = new String[input.readInt()];
				for (int i = 0; i < this.disabledUsernames.length; i++) {
					byte[] disabledUsernamesTmp = new byte[input.readInt()];
					input.readFully(disabledUsernamesTmp);
					this.disabledUsernames[i] = new String(disabledUsernamesTmp, StandardCharsets.UTF_8);
				}
			}
			if (input.readBoolean()) {
				byte[] editableUsernameTmp = new byte[input.readInt()];
				input.readFully(editableUsernameTmp);
				this.editableUsername = new String(editableUsernameTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return Usernames.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(Usernames.CONSTRUCTOR);
			if (this.activeUsernames == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.activeUsernames.length);
				for (int i = 0; i < this.activeUsernames.length; i++) {
					byte[] activeUsernamesTmp = this.activeUsernames[i].getBytes(StandardCharsets.UTF_8);
					output.writeInt(activeUsernamesTmp.length);
					output.write(activeUsernamesTmp);
				}
			}
			if (this.disabledUsernames == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.disabledUsernames.length);
				for (int i = 0; i < this.disabledUsernames.length; i++) {
					byte[] disabledUsernamesTmp = this.disabledUsernames[i].getBytes(StandardCharsets.UTF_8);
					output.writeInt(disabledUsernamesTmp.length);
					output.write(disabledUsernamesTmp);
				}
			}
			if (this.editableUsername == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] editableUsernameTmp = this.editableUsername.getBytes(StandardCharsets.UTF_8);
				output.writeInt(editableUsernameTmp.length);
				output.write(editableUsernameTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			Usernames usernames = (Usernames) o;
			if (!Arrays.equals(this.activeUsernames, usernames.activeUsernames)) {
				return false;
			}
			if (!Arrays.equals(this.disabledUsernames, usernames.disabledUsernames)) {
				return false;
			}
			if (this.editableUsername != usernames.editableUsername) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Arrays.hashCode(this.activeUsernames);
			result = result * 31 + (Arrays.hashCode(this.disabledUsernames));
			result = result * 31 + (this.editableUsername == null ? 0 : this.editableUsername.hashCode());
			return result;
		}
	}

	/**
	 * Represents a list of users.
	**/
	public static final class Users extends Object {


		/**
		 * Approximate total number of users found.
		**/
		public int totalCount;

		/**
		 * A list of user identifiers.
		**/
		public long[] userIds;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 171203420;

		/**
		 * Represents a list of users.
		**/
		public Users() {}

		/**
		 * Represents a list of users.
		 *
		 * @param totalCount Approximate total number of users found.
		 * @param userIds A list of user identifiers.
		**/
		public Users(int totalCount, long[] userIds) {
			this.totalCount = totalCount;
			this.userIds = userIds;
		}

		/**
		 * Represents a list of users.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public Users(DataInput input) throws IOException {
			this.totalCount = input.readInt();
			if (input.readBoolean()) {
				this.userIds = new long[input.readInt()];
				for (int i = 0; i < this.userIds.length; i++) {
					this.userIds[i] = input.readLong();
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return Users.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(Users.CONSTRUCTOR);
			output.writeInt(this.totalCount);
			if (this.userIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.userIds.length);
				for (int i = 0; i < this.userIds.length; i++) {
					output.writeLong(this.userIds[i]);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			Users users = (Users) o;
			if (this.totalCount != users.totalCount) {
				return false;
			}
			if (!Arrays.equals(this.userIds, users.userIds)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.totalCount);
			result = result * 31 + (Arrays.hashCode(this.userIds));
			return result;
		}
	}

	/**
	 * Contains a temporary identifier of validated order information, which
	 * is stored for one hour, and the available shipping options.
	**/
	public static final class ValidatedOrderInfo extends Object {


		/**
		 * Temporary identifier of the order information.
		**/
		public String orderInfoId;

		/**
		 * Available shipping options.
		**/
		public ShippingOption[] shippingOptions;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1511451484;

		/**
		 * Contains a temporary identifier of validated order information, which is stored for one hour, and the available shipping options.
		**/
		public ValidatedOrderInfo() {}

		/**
		 * Contains a temporary identifier of validated order information, which is stored for one hour, and the available shipping options.
		 *
		 * @param orderInfoId Temporary identifier of the order information.
		 * @param shippingOptions Available shipping options.
		**/
		public ValidatedOrderInfo(String orderInfoId, ShippingOption[] shippingOptions) {
			this.orderInfoId = orderInfoId;
			this.shippingOptions = shippingOptions;
		}

		/**
		 * Contains a temporary identifier of validated order information, which is stored for one hour, and the available shipping options.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ValidatedOrderInfo(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] orderInfoIdTmp = new byte[input.readInt()];
				input.readFully(orderInfoIdTmp);
				this.orderInfoId = new String(orderInfoIdTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				this.shippingOptions = new ShippingOption[input.readInt()];
				for (int i = 0; i < this.shippingOptions.length; i++) {
					if (ShippingOption.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.shippingOptions[i] = new ShippingOption(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ValidatedOrderInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ValidatedOrderInfo.CONSTRUCTOR);
			if (this.orderInfoId == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] orderInfoIdTmp = this.orderInfoId.getBytes(StandardCharsets.UTF_8);
				output.writeInt(orderInfoIdTmp.length);
				output.write(orderInfoIdTmp);
			}
			if (this.shippingOptions == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.shippingOptions.length);
				for (int i = 0; i < this.shippingOptions.length; i++) {
					this.shippingOptions[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ValidatedOrderInfo validatedOrderInfo = (ValidatedOrderInfo) o;
			if (this.orderInfoId != validatedOrderInfo.orderInfoId) {
				return false;
			}
			if (!Arrays.equals(this.shippingOptions, validatedOrderInfo.shippingOptions)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.orderInfoId == null ? 0 : this.orderInfoId.hashCode();
			result = result * 31 + (Arrays.hashCode(this.shippingOptions));
			return result;
		}
	}

	/**
	 * A straight line to a given point.
	**/
	public static final class VectorPathCommandLine extends VectorPathCommand {


		/**
		 * The end point of the straight line.
		**/
		public Point endPoint;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -614056822;

		/**
		 * A straight line to a given point.
		**/
		public VectorPathCommandLine() {}

		/**
		 * A straight line to a given point.
		 *
		 * @param endPoint The end point of the straight line.
		**/
		public VectorPathCommandLine(Point endPoint) {
			this.endPoint = endPoint;
		}

		/**
		 * A straight line to a given point.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public VectorPathCommandLine(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Point.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.endPoint = new Point(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return VectorPathCommandLine.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(VectorPathCommandLine.CONSTRUCTOR);
			if (this.endPoint == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.endPoint.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			VectorPathCommandLine vectorPathCommandLine = (VectorPathCommandLine) o;
			if (!Objects.equals(this.endPoint, vectorPathCommandLine.endPoint)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.endPoint == null ? 0 : this.endPoint.hashCode();
		}
	}

	/**
	 * A cubic Bézier curve to a given point.
	**/
	public static final class VectorPathCommandCubicBezierCurve extends VectorPathCommand {


		/**
		 * The start control point of the curve.
		**/
		public Point startControlPoint;

		/**
		 * The end control point of the curve.
		**/
		public Point endControlPoint;

		/**
		 * The end point of the curve.
		**/
		public Point endPoint;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1229733434;

		/**
		 * A cubic Bézier curve to a given point.
		**/
		public VectorPathCommandCubicBezierCurve() {}

		/**
		 * A cubic Bézier curve to a given point.
		 *
		 * @param startControlPoint The start control point of the curve.
		 * @param endControlPoint The end control point of the curve.
		 * @param endPoint The end point of the curve.
		**/
		public VectorPathCommandCubicBezierCurve(Point startControlPoint,
				Point endControlPoint,
				Point endPoint) {
			this.startControlPoint = startControlPoint;
			this.endControlPoint = endControlPoint;
			this.endPoint = endPoint;
		}

		/**
		 * A cubic Bézier curve to a given point.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public VectorPathCommandCubicBezierCurve(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Point.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.startControlPoint = new Point(input);
			}
			if (input.readBoolean()) {
				if (Point.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.endControlPoint = new Point(input);
			}
			if (input.readBoolean()) {
				if (Point.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.endPoint = new Point(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return VectorPathCommandCubicBezierCurve.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(VectorPathCommandCubicBezierCurve.CONSTRUCTOR);
			if (this.startControlPoint == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.startControlPoint.serialize(output);
			}
			if (this.endControlPoint == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.endControlPoint.serialize(output);
			}
			if (this.endPoint == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.endPoint.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			VectorPathCommandCubicBezierCurve vectorPathCommandCubicBezierCurve = (VectorPathCommandCubicBezierCurve) o;
			if (!Objects.equals(this.startControlPoint, vectorPathCommandCubicBezierCurve.startControlPoint)) {
				return false;
			}
			if (!Objects.equals(this.endControlPoint, vectorPathCommandCubicBezierCurve.endControlPoint)) {
				return false;
			}
			if (!Objects.equals(this.endPoint, vectorPathCommandCubicBezierCurve.endPoint)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.startControlPoint == null ? 0 : this.startControlPoint.hashCode();
			result = result * 31 + (this.endControlPoint == null ? 0 : this.endControlPoint.hashCode());
			result = result * 31 + (this.endPoint == null ? 0 : this.endPoint.hashCode());
			return result;
		}
	}

	/**
	 * Describes a venue.
	**/
	public static final class Venue extends Object {


		/**
		 * Venue location; as defined by the sender.
		**/
		public Location location;

		/**
		 * Venue name; as defined by the sender.
		**/
		public String title;

		/**
		 * Venue address; as defined by the sender.
		**/
		public String address;

		/**
		 * Provider of the venue database; as defined by the sender. Currently, only &quot;foursquare&quot; and &quot;gplaces&quot; (Google Places) need to be supported.
		**/
		public String provider;

		/**
		 * Identifier of the venue in the provider database; as defined by the sender.
		**/
		public String id;

		/**
		 * Type of the venue in the provider database; as defined by the sender.
		**/
		public String type;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1070406393;

		/**
		 * Describes a venue.
		**/
		public Venue() {}

		/**
		 * Describes a venue.
		 *
		 * @param location Venue location; as defined by the sender.
		 * @param title Venue name; as defined by the sender.
		 * @param address Venue address; as defined by the sender.
		 * @param provider Provider of the venue database; as defined by the sender. Currently, only &quot;foursquare&quot; and &quot;gplaces&quot; (Google Places) need to be supported.
		 * @param id Identifier of the venue in the provider database; as defined by the sender.
		 * @param type Type of the venue in the provider database; as defined by the sender.
		**/
		public Venue(Location location,
				String title,
				String address,
				String provider,
				String id,
				String type) {
			this.location = location;
			this.title = title;
			this.address = address;
			this.provider = provider;
			this.id = id;
			this.type = type;
		}

		/**
		 * Describes a venue.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public Venue(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Location.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.location = new Location(input);
			}
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] addressTmp = new byte[input.readInt()];
				input.readFully(addressTmp);
				this.address = new String(addressTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] providerTmp = new byte[input.readInt()];
				input.readFully(providerTmp);
				this.provider = new String(providerTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] idTmp = new byte[input.readInt()];
				input.readFully(idTmp);
				this.id = new String(idTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] typeTmp = new byte[input.readInt()];
				input.readFully(typeTmp);
				this.type = new String(typeTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return Venue.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(Venue.CONSTRUCTOR);
			if (this.location == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.location.serialize(output);
			}
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
			if (this.address == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] addressTmp = this.address.getBytes(StandardCharsets.UTF_8);
				output.writeInt(addressTmp.length);
				output.write(addressTmp);
			}
			if (this.provider == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] providerTmp = this.provider.getBytes(StandardCharsets.UTF_8);
				output.writeInt(providerTmp.length);
				output.write(providerTmp);
			}
			if (this.id == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] idTmp = this.id.getBytes(StandardCharsets.UTF_8);
				output.writeInt(idTmp.length);
				output.write(idTmp);
			}
			if (this.type == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] typeTmp = this.type.getBytes(StandardCharsets.UTF_8);
				output.writeInt(typeTmp.length);
				output.write(typeTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			Venue venue = (Venue) o;
			if (!Objects.equals(this.location, venue.location)) {
				return false;
			}
			if (this.title != venue.title) {
				return false;
			}
			if (this.address != venue.address) {
				return false;
			}
			if (this.provider != venue.provider) {
				return false;
			}
			if (this.id != venue.id) {
				return false;
			}
			if (this.type != venue.type) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.location == null ? 0 : this.location.hashCode();
			result = result * 31 + (this.title == null ? 0 : this.title.hashCode());
			result = result * 31 + (this.address == null ? 0 : this.address.hashCode());
			result = result * 31 + (this.provider == null ? 0 : this.provider.hashCode());
			result = result * 31 + (this.id == null ? 0 : this.id.hashCode());
			result = result * 31 + (this.type == null ? 0 : this.type.hashCode());
			return result;
		}
	}

	/**
	 * Describes a video file.
	**/
	public static final class Video extends Object {


		/**
		 * Duration of the video, in seconds; as defined by the sender.
		**/
		public int duration;

		/**
		 * Video width; as defined by the sender.
		**/
		public int width;

		/**
		 * Video height; as defined by the sender.
		**/
		public int height;

		/**
		 * Original name of the file; as defined by the sender.
		**/
		public String fileName;

		/**
		 * MIME type of the file; as defined by the sender.
		**/
		public String mimeType;

		/**
		 * True, if stickers were added to the video. The list of corresponding sticker sets can be received using getAttachedStickerSets.
		**/
		public boolean hasStickers;

		/**
		 * True, if the video is supposed to be streamed.
		**/
		public boolean supportsStreaming;

		/**
		 * Video minithumbnail; may be null.
		**/
		public Minithumbnail minithumbnail;

		/**
		 * Video thumbnail in JPEG or MPEG4 format; as defined by the sender; may be null.
		**/
		public Thumbnail thumbnail;

		/**
		 * File containing the video.
		**/
		public File video;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 832856268;

		/**
		 * Describes a video file.
		**/
		public Video() {}

		/**
		 * Describes a video file.
		 *
		 * @param duration Duration of the video, in seconds; as defined by the sender.
		 * @param width Video width; as defined by the sender.
		 * @param height Video height; as defined by the sender.
		 * @param fileName Original name of the file; as defined by the sender.
		 * @param mimeType MIME type of the file; as defined by the sender.
		 * @param hasStickers True, if stickers were added to the video. The list of corresponding sticker sets can be received using getAttachedStickerSets.
		 * @param supportsStreaming True, if the video is supposed to be streamed.
		 * @param minithumbnail Video minithumbnail; may be null.
		 * @param thumbnail Video thumbnail in JPEG or MPEG4 format; as defined by the sender; may be null.
		 * @param video File containing the video.
		**/
		public Video(int duration,
				int width,
				int height,
				String fileName,
				String mimeType,
				boolean hasStickers,
				boolean supportsStreaming,
				Minithumbnail minithumbnail,
				Thumbnail thumbnail,
				File video) {
			this.duration = duration;
			this.width = width;
			this.height = height;
			this.fileName = fileName;
			this.mimeType = mimeType;
			this.hasStickers = hasStickers;
			this.supportsStreaming = supportsStreaming;
			this.minithumbnail = minithumbnail;
			this.thumbnail = thumbnail;
			this.video = video;
		}

		/**
		 * Describes a video file.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public Video(DataInput input) throws IOException {
			this.duration = input.readInt();
			this.width = input.readInt();
			this.height = input.readInt();
			if (input.readBoolean()) {
				byte[] fileNameTmp = new byte[input.readInt()];
				input.readFully(fileNameTmp);
				this.fileName = new String(fileNameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] mimeTypeTmp = new byte[input.readInt()];
				input.readFully(mimeTypeTmp);
				this.mimeType = new String(mimeTypeTmp, StandardCharsets.UTF_8);
			}
			this.hasStickers = input.readBoolean();
			this.supportsStreaming = input.readBoolean();
			if (input.readBoolean()) {
				if (Minithumbnail.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.minithumbnail = new Minithumbnail(input);
			}
			if (input.readBoolean()) {
				if (Thumbnail.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.thumbnail = new Thumbnail(input);
			}
			if (input.readBoolean()) {
				if (File.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.video = new File(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return Video.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(Video.CONSTRUCTOR);
			output.writeInt(this.duration);
			output.writeInt(this.width);
			output.writeInt(this.height);
			if (this.fileName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] fileNameTmp = this.fileName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(fileNameTmp.length);
				output.write(fileNameTmp);
			}
			if (this.mimeType == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] mimeTypeTmp = this.mimeType.getBytes(StandardCharsets.UTF_8);
				output.writeInt(mimeTypeTmp.length);
				output.write(mimeTypeTmp);
			}
			output.writeBoolean(this.hasStickers);
			output.writeBoolean(this.supportsStreaming);
			if (this.minithumbnail == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.minithumbnail.serialize(output);
			}
			if (this.thumbnail == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.thumbnail.serialize(output);
			}
			if (this.video == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.video.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			Video video = (Video) o;
			if (this.duration != video.duration) {
				return false;
			}
			if (this.width != video.width) {
				return false;
			}
			if (this.height != video.height) {
				return false;
			}
			if (this.fileName != video.fileName) {
				return false;
			}
			if (this.mimeType != video.mimeType) {
				return false;
			}
			if (this.hasStickers != video.hasStickers) {
				return false;
			}
			if (this.supportsStreaming != video.supportsStreaming) {
				return false;
			}
			if (!Objects.equals(this.minithumbnail, video.minithumbnail)) {
				return false;
			}
			if (!Objects.equals(this.thumbnail, video.thumbnail)) {
				return false;
			}
			if (!Objects.equals(this.video, video.video)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.duration);
			result = result * 31 + (this.fileName == null ? 0 : this.fileName.hashCode());
			result = result * 31 + (this.mimeType == null ? 0 : this.mimeType.hashCode());
			result = result * 31 + (this.minithumbnail == null ? 0 : this.minithumbnail.hashCode());
			result = result * 31 + (this.thumbnail == null ? 0 : this.thumbnail.hashCode());
			result = result * 31 + (this.video == null ? 0 : this.video.hashCode());
			return result;
		}
	}

	/**
	 * Describes a video chat.
	**/
	public static final class VideoChat extends Object {


		/**
		 * Group call identifier of an active video chat; 0 if none. Full information about the video chat can be received through the method getGroupCall.
		**/
		public int groupCallId;

		/**
		 * True, if the video chat has participants.
		**/
		public boolean hasParticipants;

		/**
		 * Default group call participant identifier to join the video chat; may be null.
		**/
		public MessageSender defaultParticipantId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1374319320;

		/**
		 * Describes a video chat.
		**/
		public VideoChat() {}

		/**
		 * Describes a video chat.
		 *
		 * @param groupCallId Group call identifier of an active video chat; 0 if none. Full information about the video chat can be received through the method getGroupCall.
		 * @param hasParticipants True, if the video chat has participants.
		 * @param defaultParticipantId Default group call participant identifier to join the video chat; may be null.
		**/
		public VideoChat(int groupCallId,
				boolean hasParticipants,
				MessageSender defaultParticipantId) {
			this.groupCallId = groupCallId;
			this.hasParticipants = hasParticipants;
			this.defaultParticipantId = defaultParticipantId;
		}

		/**
		 * Describes a video chat.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public VideoChat(DataInput input) throws IOException {
			this.groupCallId = input.readInt();
			this.hasParticipants = input.readBoolean();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case MessageSenderUser.CONSTRUCTOR: this.defaultParticipantId = new MessageSenderUser(input); break;
					case MessageSenderChat.CONSTRUCTOR: this.defaultParticipantId = new MessageSenderChat(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return VideoChat.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(VideoChat.CONSTRUCTOR);
			output.writeInt(this.groupCallId);
			output.writeBoolean(this.hasParticipants);
			if (this.defaultParticipantId == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.defaultParticipantId.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			VideoChat videoChat = (VideoChat) o;
			if (this.groupCallId != videoChat.groupCallId) {
				return false;
			}
			if (this.hasParticipants != videoChat.hasParticipants) {
				return false;
			}
			if (!Objects.equals(this.defaultParticipantId, videoChat.defaultParticipantId)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.groupCallId);
			result = result * 31 + (this.defaultParticipantId == null ? 0 : this.defaultParticipantId.hashCode());
			return result;
		}
	}

	/**
	 * Describes a video note. The video must be equal in width and height,
	 * cropped to a circle, and stored in MPEG4 format.
	**/
	public static final class VideoNote extends Object {


		/**
		 * Duration of the video, in seconds; as defined by the sender.
		**/
		public int duration;

		/**
		 * A waveform representation of the video note&#039;s audio in 5-bit format; may be empty if unknown.
		**/
		public byte[] waveform;

		/**
		 * Video width and height; as defined by the sender.
		**/
		public int length;

		/**
		 * Video minithumbnail; may be null.
		**/
		public Minithumbnail minithumbnail;

		/**
		 * Video thumbnail in JPEG format; as defined by the sender; may be null.
		**/
		public Thumbnail thumbnail;

		/**
		 * Result of speech recognition in the video note; may be null.
		**/
		public SpeechRecognitionResult speechRecognitionResult;

		/**
		 * File containing the video.
		**/
		public File video;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2062096581;

		/**
		 * Describes a video note. The video must be equal in width and height, cropped to a circle, and stored in MPEG4 format.
		**/
		public VideoNote() {}

		/**
		 * Describes a video note. The video must be equal in width and height, cropped to a circle, and stored in MPEG4 format.
		 *
		 * @param duration Duration of the video, in seconds; as defined by the sender.
		 * @param waveform A waveform representation of the video note&#039;s audio in 5-bit format; may be empty if unknown.
		 * @param length Video width and height; as defined by the sender.
		 * @param minithumbnail Video minithumbnail; may be null.
		 * @param thumbnail Video thumbnail in JPEG format; as defined by the sender; may be null.
		 * @param speechRecognitionResult Result of speech recognition in the video note; may be null.
		 * @param video File containing the video.
		**/
		public VideoNote(int duration,
				byte[] waveform,
				int length,
				Minithumbnail minithumbnail,
				Thumbnail thumbnail,
				SpeechRecognitionResult speechRecognitionResult,
				File video) {
			this.duration = duration;
			this.waveform = waveform;
			this.length = length;
			this.minithumbnail = minithumbnail;
			this.thumbnail = thumbnail;
			this.speechRecognitionResult = speechRecognitionResult;
			this.video = video;
		}

		/**
		 * Describes a video note. The video must be equal in width and height, cropped to a circle, and stored in MPEG4 format.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public VideoNote(DataInput input) throws IOException {
			this.duration = input.readInt();
			if (input.readBoolean()) {
				this.waveform = new byte[input.readInt()];
				input.readFully(this.waveform);
			}
			this.length = input.readInt();
			if (input.readBoolean()) {
				if (Minithumbnail.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.minithumbnail = new Minithumbnail(input);
			}
			if (input.readBoolean()) {
				if (Thumbnail.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.thumbnail = new Thumbnail(input);
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case SpeechRecognitionResultPending.CONSTRUCTOR: this.speechRecognitionResult = new SpeechRecognitionResultPending(input); break;
					case SpeechRecognitionResultText.CONSTRUCTOR: this.speechRecognitionResult = new SpeechRecognitionResultText(input); break;
					case SpeechRecognitionResultError.CONSTRUCTOR: this.speechRecognitionResult = new SpeechRecognitionResultError(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				if (File.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.video = new File(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return VideoNote.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(VideoNote.CONSTRUCTOR);
			output.writeInt(this.duration);
			if (this.waveform == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.waveform.length);
				output.write(this.waveform);
			}
			output.writeInt(this.length);
			if (this.minithumbnail == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.minithumbnail.serialize(output);
			}
			if (this.thumbnail == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.thumbnail.serialize(output);
			}
			if (this.speechRecognitionResult == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.speechRecognitionResult.serialize(output);
			}
			if (this.video == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.video.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			VideoNote videoNote = (VideoNote) o;
			if (this.duration != videoNote.duration) {
				return false;
			}
			if (this.waveform != videoNote.waveform) {
				return false;
			}
			if (this.length != videoNote.length) {
				return false;
			}
			if (!Objects.equals(this.minithumbnail, videoNote.minithumbnail)) {
				return false;
			}
			if (!Objects.equals(this.thumbnail, videoNote.thumbnail)) {
				return false;
			}
			if (!Objects.equals(this.speechRecognitionResult, videoNote.speechRecognitionResult)) {
				return false;
			}
			if (!Objects.equals(this.video, videoNote.video)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.duration);
			result = result * 31 + (Arrays.hashCode(this.waveform));
			result = result * 31 + (this.minithumbnail == null ? 0 : this.minithumbnail.hashCode());
			result = result * 31 + (this.thumbnail == null ? 0 : this.thumbnail.hashCode());
			result = result * 31 + (this.speechRecognitionResult == null ? 0 : this.speechRecognitionResult.hashCode());
			result = result * 31 + (this.video == null ? 0 : this.video.hashCode());
			return result;
		}
	}

	/**
	 * Describes a voice note. The voice note must be encoded with the Opus
	 * codec, and stored inside an OGG container. Voice notes can have only
	 * a single audio channel.
	**/
	public static final class VoiceNote extends Object {


		/**
		 * Duration of the voice note, in seconds; as defined by the sender.
		**/
		public int duration;

		/**
		 * A waveform representation of the voice note in 5-bit format.
		**/
		public byte[] waveform;

		/**
		 * MIME type of the file; as defined by the sender.
		**/
		public String mimeType;

		/**
		 * Result of speech recognition in the voice note; may be null.
		**/
		public SpeechRecognitionResult speechRecognitionResult;

		/**
		 * File containing the voice note.
		**/
		public File voice;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1175302923;

		/**
		 * Describes a voice note. The voice note must be encoded with the Opus codec, and stored inside an OGG container. Voice notes can have only a single audio channel.
		**/
		public VoiceNote() {}

		/**
		 * Describes a voice note. The voice note must be encoded with the Opus codec, and stored inside an OGG container. Voice notes can have only a single audio channel.
		 *
		 * @param duration Duration of the voice note, in seconds; as defined by the sender.
		 * @param waveform A waveform representation of the voice note in 5-bit format.
		 * @param mimeType MIME type of the file; as defined by the sender.
		 * @param speechRecognitionResult Result of speech recognition in the voice note; may be null.
		 * @param voice File containing the voice note.
		**/
		public VoiceNote(int duration,
				byte[] waveform,
				String mimeType,
				SpeechRecognitionResult speechRecognitionResult,
				File voice) {
			this.duration = duration;
			this.waveform = waveform;
			this.mimeType = mimeType;
			this.speechRecognitionResult = speechRecognitionResult;
			this.voice = voice;
		}

		/**
		 * Describes a voice note. The voice note must be encoded with the Opus codec, and stored inside an OGG container. Voice notes can have only a single audio channel.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public VoiceNote(DataInput input) throws IOException {
			this.duration = input.readInt();
			if (input.readBoolean()) {
				this.waveform = new byte[input.readInt()];
				input.readFully(this.waveform);
			}
			if (input.readBoolean()) {
				byte[] mimeTypeTmp = new byte[input.readInt()];
				input.readFully(mimeTypeTmp);
				this.mimeType = new String(mimeTypeTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case SpeechRecognitionResultPending.CONSTRUCTOR: this.speechRecognitionResult = new SpeechRecognitionResultPending(input); break;
					case SpeechRecognitionResultText.CONSTRUCTOR: this.speechRecognitionResult = new SpeechRecognitionResultText(input); break;
					case SpeechRecognitionResultError.CONSTRUCTOR: this.speechRecognitionResult = new SpeechRecognitionResultError(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				if (File.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.voice = new File(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return VoiceNote.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(VoiceNote.CONSTRUCTOR);
			output.writeInt(this.duration);
			if (this.waveform == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.waveform.length);
				output.write(this.waveform);
			}
			if (this.mimeType == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] mimeTypeTmp = this.mimeType.getBytes(StandardCharsets.UTF_8);
				output.writeInt(mimeTypeTmp.length);
				output.write(mimeTypeTmp);
			}
			if (this.speechRecognitionResult == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.speechRecognitionResult.serialize(output);
			}
			if (this.voice == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.voice.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			VoiceNote voiceNote = (VoiceNote) o;
			if (this.duration != voiceNote.duration) {
				return false;
			}
			if (this.waveform != voiceNote.waveform) {
				return false;
			}
			if (this.mimeType != voiceNote.mimeType) {
				return false;
			}
			if (!Objects.equals(this.speechRecognitionResult, voiceNote.speechRecognitionResult)) {
				return false;
			}
			if (!Objects.equals(this.voice, voiceNote.voice)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.duration);
			result = result * 31 + (Arrays.hashCode(this.waveform));
			result = result * 31 + (this.mimeType == null ? 0 : this.mimeType.hashCode());
			result = result * 31 + (this.speechRecognitionResult == null ? 0 : this.speechRecognitionResult.hashCode());
			result = result * 31 + (this.voice == null ? 0 : this.voice.hashCode());
			return result;
		}
	}

	/**
	 * Describes a Web App. Use getInternalLink with internalLinkTypeWebApp
	 * to share the Web App.
	**/
	public static final class WebApp extends Object {


		/**
		 * Web App short name.
		**/
		public String shortName;

		/**
		 * Web App title.
		**/
		public String title;

		/**
		 * Web App description.
		**/
		public String description;

		/**
		 * Web App photo.
		**/
		public Photo photo;

		/**
		 * Web App animation; may be null.
		**/
		public Animation animation;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1616619763;

		/**
		 * Describes a Web App. Use getInternalLink with internalLinkTypeWebApp to share the Web App.
		**/
		public WebApp() {}

		/**
		 * Describes a Web App. Use getInternalLink with internalLinkTypeWebApp to share the Web App.
		 *
		 * @param shortName Web App short name.
		 * @param title Web App title.
		 * @param description Web App description.
		 * @param photo Web App photo.
		 * @param animation Web App animation; may be null.
		**/
		public WebApp(String shortName,
				String title,
				String description,
				Photo photo,
				Animation animation) {
			this.shortName = shortName;
			this.title = title;
			this.description = description;
			this.photo = photo;
			this.animation = animation;
		}

		/**
		 * Describes a Web App. Use getInternalLink with internalLinkTypeWebApp to share the Web App.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public WebApp(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] shortNameTmp = new byte[input.readInt()];
				input.readFully(shortNameTmp);
				this.shortName = new String(shortNameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] descriptionTmp = new byte[input.readInt()];
				input.readFully(descriptionTmp);
				this.description = new String(descriptionTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (Photo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.photo = new Photo(input);
			}
			if (input.readBoolean()) {
				if (Animation.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.animation = new Animation(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return WebApp.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(WebApp.CONSTRUCTOR);
			if (this.shortName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] shortNameTmp = this.shortName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(shortNameTmp.length);
				output.write(shortNameTmp);
			}
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
			if (this.description == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] descriptionTmp = this.description.getBytes(StandardCharsets.UTF_8);
				output.writeInt(descriptionTmp.length);
				output.write(descriptionTmp);
			}
			if (this.photo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.photo.serialize(output);
			}
			if (this.animation == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.animation.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			WebApp webApp = (WebApp) o;
			if (this.shortName != webApp.shortName) {
				return false;
			}
			if (this.title != webApp.title) {
				return false;
			}
			if (this.description != webApp.description) {
				return false;
			}
			if (!Objects.equals(this.photo, webApp.photo)) {
				return false;
			}
			if (!Objects.equals(this.animation, webApp.animation)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.shortName == null ? 0 : this.shortName.hashCode();
			result = result * 31 + (this.title == null ? 0 : this.title.hashCode());
			result = result * 31 + (this.description == null ? 0 : this.description.hashCode());
			result = result * 31 + (this.photo == null ? 0 : this.photo.hashCode());
			result = result * 31 + (this.animation == null ? 0 : this.animation.hashCode());
			return result;
		}
	}

	/**
	 * Contains information about a Web App.
	**/
	public static final class WebAppInfo extends Object {


		/**
		 * Unique identifier for the Web App launch.
		**/
		public long launchId;

		/**
		 * A Web App URL to open in a web view.
		**/
		public String url;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 788378344;

		/**
		 * Contains information about a Web App.
		**/
		public WebAppInfo() {}

		/**
		 * Contains information about a Web App.
		 *
		 * @param launchId Unique identifier for the Web App launch.
		 * @param url A Web App URL to open in a web view.
		**/
		public WebAppInfo(long launchId, String url) {
			this.launchId = launchId;
			this.url = url;
		}

		/**
		 * Contains information about a Web App.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public WebAppInfo(DataInput input) throws IOException {
			this.launchId = input.readLong();
			if (input.readBoolean()) {
				byte[] urlTmp = new byte[input.readInt()];
				input.readFully(urlTmp);
				this.url = new String(urlTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return WebAppInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(WebAppInfo.CONSTRUCTOR);
			output.writeLong(this.launchId);
			if (this.url == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] urlTmp = this.url.getBytes(StandardCharsets.UTF_8);
				output.writeInt(urlTmp.length);
				output.write(urlTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			WebAppInfo webAppInfo = (WebAppInfo) o;
			if (this.launchId != webAppInfo.launchId) {
				return false;
			}
			if (this.url != webAppInfo.url) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.launchId);
			result = result * 31 + (this.url == null ? 0 : this.url.hashCode());
			return result;
		}
	}

	/**
	 * Describes a web page preview.
	**/
	public static final class WebPage extends Object {


		/**
		 * Original URL of the link.
		**/
		public String url;

		/**
		 * URL to display.
		**/
		public String displayUrl;

		/**
		 * Type of the web page. Can be: article, photo, audio, video, document, profile, app, or something else.
		**/
		public String type;

		/**
		 * Short name of the site (e.g., Google Docs, App Store).
		**/
		public String siteName;

		/**
		 * Title of the content.
		**/
		public String title;

		/**
		 * Description of the content.
		**/
		public FormattedText description;

		/**
		 * Image representing the content; may be null.
		**/
		public Photo photo;

		/**
		 * URL to show in the embedded preview.
		**/
		public String embedUrl;

		/**
		 * MIME type of the embedded preview, (e.g., text/html or video/mp4).
		**/
		public String embedType;

		/**
		 * Width of the embedded preview.
		**/
		public int embedWidth;

		/**
		 * Height of the embedded preview.
		**/
		public int embedHeight;

		/**
		 * Duration of the content, in seconds.
		**/
		public int duration;

		/**
		 * Author of the content.
		**/
		public String author;

		/**
		 * Preview of the content as an animation, if available; may be null.
		**/
		public Animation animation;

		/**
		 * Preview of the content as an audio file, if available; may be null.
		**/
		public Audio audio;

		/**
		 * Preview of the content as a document, if available; may be null.
		**/
		public Document document;

		/**
		 * Preview of the content as a sticker for small WEBP files, if available; may be null.
		**/
		public Sticker sticker;

		/**
		 * Preview of the content as a video, if available; may be null.
		**/
		public Video video;

		/**
		 * Preview of the content as a video note, if available; may be null.
		**/
		public VideoNote videoNote;

		/**
		 * Preview of the content as a voice note, if available; may be null.
		**/
		public VoiceNote voiceNote;

		/**
		 * Version of web page instant view (currently, can be 1 or 2); 0 if none.
		**/
		public int instantViewVersion;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -577333714;

		/**
		 * Describes a web page preview.
		**/
		public WebPage() {}

		/**
		 * Describes a web page preview.
		 *
		 * @param url Original URL of the link.
		 * @param displayUrl URL to display.
		 * @param type Type of the web page. Can be: article, photo, audio, video, document, profile, app, or something else.
		 * @param siteName Short name of the site (e.g., Google Docs, App Store).
		 * @param title Title of the content.
		 * @param description Description of the content.
		 * @param photo Image representing the content; may be null.
		 * @param embedUrl URL to show in the embedded preview.
		 * @param embedType MIME type of the embedded preview, (e.g., text/html or video/mp4).
		 * @param embedWidth Width of the embedded preview.
		 * @param embedHeight Height of the embedded preview.
		 * @param duration Duration of the content, in seconds.
		 * @param author Author of the content.
		 * @param animation Preview of the content as an animation, if available; may be null.
		 * @param audio Preview of the content as an audio file, if available; may be null.
		 * @param document Preview of the content as a document, if available; may be null.
		 * @param sticker Preview of the content as a sticker for small WEBP files, if available; may be null.
		 * @param video Preview of the content as a video, if available; may be null.
		 * @param videoNote Preview of the content as a video note, if available; may be null.
		 * @param voiceNote Preview of the content as a voice note, if available; may be null.
		 * @param instantViewVersion Version of web page instant view (currently, can be 1 or 2); 0 if none.
		**/
		public WebPage(String url,
				String displayUrl,
				String type,
				String siteName,
				String title,
				FormattedText description,
				Photo photo,
				String embedUrl,
				String embedType,
				int embedWidth,
				int embedHeight,
				int duration,
				String author,
				Animation animation,
				Audio audio,
				Document document,
				Sticker sticker,
				Video video,
				VideoNote videoNote,
				VoiceNote voiceNote,
				int instantViewVersion) {
			this.url = url;
			this.displayUrl = displayUrl;
			this.type = type;
			this.siteName = siteName;
			this.title = title;
			this.description = description;
			this.photo = photo;
			this.embedUrl = embedUrl;
			this.embedType = embedType;
			this.embedWidth = embedWidth;
			this.embedHeight = embedHeight;
			this.duration = duration;
			this.author = author;
			this.animation = animation;
			this.audio = audio;
			this.document = document;
			this.sticker = sticker;
			this.video = video;
			this.videoNote = videoNote;
			this.voiceNote = voiceNote;
			this.instantViewVersion = instantViewVersion;
		}

		/**
		 * Describes a web page preview.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public WebPage(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] urlTmp = new byte[input.readInt()];
				input.readFully(urlTmp);
				this.url = new String(urlTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] displayUrlTmp = new byte[input.readInt()];
				input.readFully(displayUrlTmp);
				this.displayUrl = new String(displayUrlTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] typeTmp = new byte[input.readInt()];
				input.readFully(typeTmp);
				this.type = new String(typeTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] siteNameTmp = new byte[input.readInt()];
				input.readFully(siteNameTmp);
				this.siteName = new String(siteNameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (FormattedText.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.description = new FormattedText(input);
			}
			if (input.readBoolean()) {
				if (Photo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.photo = new Photo(input);
			}
			if (input.readBoolean()) {
				byte[] embedUrlTmp = new byte[input.readInt()];
				input.readFully(embedUrlTmp);
				this.embedUrl = new String(embedUrlTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] embedTypeTmp = new byte[input.readInt()];
				input.readFully(embedTypeTmp);
				this.embedType = new String(embedTypeTmp, StandardCharsets.UTF_8);
			}
			this.embedWidth = input.readInt();
			this.embedHeight = input.readInt();
			this.duration = input.readInt();
			if (input.readBoolean()) {
				byte[] authorTmp = new byte[input.readInt()];
				input.readFully(authorTmp);
				this.author = new String(authorTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (Animation.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.animation = new Animation(input);
			}
			if (input.readBoolean()) {
				if (Audio.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.audio = new Audio(input);
			}
			if (input.readBoolean()) {
				if (Document.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.document = new Document(input);
			}
			if (input.readBoolean()) {
				if (Sticker.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.sticker = new Sticker(input);
			}
			if (input.readBoolean()) {
				if (Video.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.video = new Video(input);
			}
			if (input.readBoolean()) {
				if (VideoNote.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.videoNote = new VideoNote(input);
			}
			if (input.readBoolean()) {
				if (VoiceNote.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.voiceNote = new VoiceNote(input);
			}
			this.instantViewVersion = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return WebPage.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(WebPage.CONSTRUCTOR);
			if (this.url == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] urlTmp = this.url.getBytes(StandardCharsets.UTF_8);
				output.writeInt(urlTmp.length);
				output.write(urlTmp);
			}
			if (this.displayUrl == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] displayUrlTmp = this.displayUrl.getBytes(StandardCharsets.UTF_8);
				output.writeInt(displayUrlTmp.length);
				output.write(displayUrlTmp);
			}
			if (this.type == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] typeTmp = this.type.getBytes(StandardCharsets.UTF_8);
				output.writeInt(typeTmp.length);
				output.write(typeTmp);
			}
			if (this.siteName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] siteNameTmp = this.siteName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(siteNameTmp.length);
				output.write(siteNameTmp);
			}
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
			if (this.description == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.description.serialize(output);
			}
			if (this.photo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.photo.serialize(output);
			}
			if (this.embedUrl == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] embedUrlTmp = this.embedUrl.getBytes(StandardCharsets.UTF_8);
				output.writeInt(embedUrlTmp.length);
				output.write(embedUrlTmp);
			}
			if (this.embedType == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] embedTypeTmp = this.embedType.getBytes(StandardCharsets.UTF_8);
				output.writeInt(embedTypeTmp.length);
				output.write(embedTypeTmp);
			}
			output.writeInt(this.embedWidth);
			output.writeInt(this.embedHeight);
			output.writeInt(this.duration);
			if (this.author == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] authorTmp = this.author.getBytes(StandardCharsets.UTF_8);
				output.writeInt(authorTmp.length);
				output.write(authorTmp);
			}
			if (this.animation == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.animation.serialize(output);
			}
			if (this.audio == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.audio.serialize(output);
			}
			if (this.document == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.document.serialize(output);
			}
			if (this.sticker == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.sticker.serialize(output);
			}
			if (this.video == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.video.serialize(output);
			}
			if (this.videoNote == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.videoNote.serialize(output);
			}
			if (this.voiceNote == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.voiceNote.serialize(output);
			}
			output.writeInt(this.instantViewVersion);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			WebPage webPage = (WebPage) o;
			if (this.url != webPage.url) {
				return false;
			}
			if (this.displayUrl != webPage.displayUrl) {
				return false;
			}
			if (this.type != webPage.type) {
				return false;
			}
			if (this.siteName != webPage.siteName) {
				return false;
			}
			if (this.title != webPage.title) {
				return false;
			}
			if (!Objects.equals(this.description, webPage.description)) {
				return false;
			}
			if (!Objects.equals(this.photo, webPage.photo)) {
				return false;
			}
			if (this.embedUrl != webPage.embedUrl) {
				return false;
			}
			if (this.embedType != webPage.embedType) {
				return false;
			}
			if (this.embedWidth != webPage.embedWidth) {
				return false;
			}
			if (this.embedHeight != webPage.embedHeight) {
				return false;
			}
			if (this.duration != webPage.duration) {
				return false;
			}
			if (this.author != webPage.author) {
				return false;
			}
			if (!Objects.equals(this.animation, webPage.animation)) {
				return false;
			}
			if (!Objects.equals(this.audio, webPage.audio)) {
				return false;
			}
			if (!Objects.equals(this.document, webPage.document)) {
				return false;
			}
			if (!Objects.equals(this.sticker, webPage.sticker)) {
				return false;
			}
			if (!Objects.equals(this.video, webPage.video)) {
				return false;
			}
			if (!Objects.equals(this.videoNote, webPage.videoNote)) {
				return false;
			}
			if (!Objects.equals(this.voiceNote, webPage.voiceNote)) {
				return false;
			}
			if (this.instantViewVersion != webPage.instantViewVersion) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.embedWidth);
			result = result * 31 + (this.url == null ? 0 : this.url.hashCode());
			result = result * 31 + (this.displayUrl == null ? 0 : this.displayUrl.hashCode());
			result = result * 31 + (this.type == null ? 0 : this.type.hashCode());
			result = result * 31 + (this.siteName == null ? 0 : this.siteName.hashCode());
			result = result * 31 + (this.title == null ? 0 : this.title.hashCode());
			result = result * 31 + (this.description == null ? 0 : this.description.hashCode());
			result = result * 31 + (this.photo == null ? 0 : this.photo.hashCode());
			result = result * 31 + (this.embedUrl == null ? 0 : this.embedUrl.hashCode());
			result = result * 31 + (this.embedType == null ? 0 : this.embedType.hashCode());
			result = result * 31 + (this.author == null ? 0 : this.author.hashCode());
			result = result * 31 + (this.animation == null ? 0 : this.animation.hashCode());
			result = result * 31 + (this.audio == null ? 0 : this.audio.hashCode());
			result = result * 31 + (this.document == null ? 0 : this.document.hashCode());
			result = result * 31 + (this.sticker == null ? 0 : this.sticker.hashCode());
			result = result * 31 + (this.video == null ? 0 : this.video.hashCode());
			result = result * 31 + (this.videoNote == null ? 0 : this.videoNote.hashCode());
			result = result * 31 + (this.voiceNote == null ? 0 : this.voiceNote.hashCode());
			return result;
		}
	}

	/**
	 * Describes an instant view page for a web page.
	**/
	public static final class WebPageInstantView extends Object {


		/**
		 * Content of the web page.
		**/
		public PageBlock[] pageBlocks;

		/**
		 * Number of the instant view views; 0 if unknown.
		**/
		public int viewCount;

		/**
		 * Version of the instant view; currently, can be 1 or 2.
		**/
		public int version;

		/**
		 * True, if the instant view must be shown from right to left.
		**/
		public boolean isRtl;

		/**
		 * True, if the instant view contains the full page. A network request might be needed to get the full web page instant view.
		**/
		public boolean isFull;

		/**
		 * An internal link to be opened to leave feedback about the instant view.
		**/
		public InternalLinkType feedbackLink;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 778202453;

		/**
		 * Describes an instant view page for a web page.
		**/
		public WebPageInstantView() {}

		/**
		 * Describes an instant view page for a web page.
		 *
		 * @param pageBlocks Content of the web page.
		 * @param viewCount Number of the instant view views; 0 if unknown.
		 * @param version Version of the instant view; currently, can be 1 or 2.
		 * @param isRtl True, if the instant view must be shown from right to left.
		 * @param isFull True, if the instant view contains the full page. A network request might be needed to get the full web page instant view.
		 * @param feedbackLink An internal link to be opened to leave feedback about the instant view.
		**/
		public WebPageInstantView(PageBlock[] pageBlocks,
				int viewCount,
				int version,
				boolean isRtl,
				boolean isFull,
				InternalLinkType feedbackLink) {
			this.pageBlocks = pageBlocks;
			this.viewCount = viewCount;
			this.version = version;
			this.isRtl = isRtl;
			this.isFull = isFull;
			this.feedbackLink = feedbackLink;
		}

		/**
		 * Describes an instant view page for a web page.
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public WebPageInstantView(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.pageBlocks = new PageBlock[input.readInt()];
				for (int i = 0; i < this.pageBlocks.length; i++) {
					switch(input.readInt()) {
						case PageBlockTitle.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockTitle(input); break;
						case PageBlockSubtitle.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockSubtitle(input); break;
						case PageBlockAuthorDate.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockAuthorDate(input); break;
						case PageBlockHeader.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockHeader(input); break;
						case PageBlockSubheader.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockSubheader(input); break;
						case PageBlockKicker.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockKicker(input); break;
						case PageBlockParagraph.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockParagraph(input); break;
						case PageBlockPreformatted.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockPreformatted(input); break;
						case PageBlockFooter.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockFooter(input); break;
						case PageBlockDivider.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockDivider(input); break;
						case PageBlockAnchor.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockAnchor(input); break;
						case PageBlockList.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockList(input); break;
						case PageBlockBlockQuote.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockBlockQuote(input); break;
						case PageBlockPullQuote.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockPullQuote(input); break;
						case PageBlockAnimation.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockAnimation(input); break;
						case PageBlockAudio.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockAudio(input); break;
						case PageBlockPhoto.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockPhoto(input); break;
						case PageBlockVideo.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockVideo(input); break;
						case PageBlockVoiceNote.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockVoiceNote(input); break;
						case PageBlockCover.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockCover(input); break;
						case PageBlockEmbedded.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockEmbedded(input); break;
						case PageBlockEmbeddedPost.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockEmbeddedPost(input); break;
						case PageBlockCollage.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockCollage(input); break;
						case PageBlockSlideshow.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockSlideshow(input); break;
						case PageBlockChatLink.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockChatLink(input); break;
						case PageBlockTable.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockTable(input); break;
						case PageBlockDetails.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockDetails(input); break;
						case PageBlockRelatedArticles.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockRelatedArticles(input); break;
						case PageBlockMap.CONSTRUCTOR: this.pageBlocks[i] = new PageBlockMap(input); break;
						default: {
							throw new UnsupportedOperationException();
						}
					}
				}
			}
			this.viewCount = input.readInt();
			this.version = input.readInt();
			this.isRtl = input.readBoolean();
			this.isFull = input.readBoolean();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InternalLinkTypeActiveSessions.CONSTRUCTOR: this.feedbackLink = new InternalLinkTypeActiveSessions(input); break;
					case InternalLinkTypeAttachmentMenuBot.CONSTRUCTOR: this.feedbackLink = new InternalLinkTypeAttachmentMenuBot(input); break;
					case InternalLinkTypeAuthenticationCode.CONSTRUCTOR: this.feedbackLink = new InternalLinkTypeAuthenticationCode(input); break;
					case InternalLinkTypeBackground.CONSTRUCTOR: this.feedbackLink = new InternalLinkTypeBackground(input); break;
					case InternalLinkTypeBotAddToChannel.CONSTRUCTOR: this.feedbackLink = new InternalLinkTypeBotAddToChannel(input); break;
					case InternalLinkTypeBotStart.CONSTRUCTOR: this.feedbackLink = new InternalLinkTypeBotStart(input); break;
					case InternalLinkTypeBotStartInGroup.CONSTRUCTOR: this.feedbackLink = new InternalLinkTypeBotStartInGroup(input); break;
					case InternalLinkTypeChangePhoneNumber.CONSTRUCTOR: this.feedbackLink = new InternalLinkTypeChangePhoneNumber(input); break;
					case InternalLinkTypeChatFolderInvite.CONSTRUCTOR: this.feedbackLink = new InternalLinkTypeChatFolderInvite(input); break;
					case InternalLinkTypeChatFolderSettings.CONSTRUCTOR: this.feedbackLink = new InternalLinkTypeChatFolderSettings(input); break;
					case InternalLinkTypeChatInvite.CONSTRUCTOR: this.feedbackLink = new InternalLinkTypeChatInvite(input); break;
					case InternalLinkTypeDefaultMessageAutoDeleteTimerSettings.CONSTRUCTOR: this.feedbackLink = new InternalLinkTypeDefaultMessageAutoDeleteTimerSettings(input); break;
					case InternalLinkTypeEditProfileSettings.CONSTRUCTOR: this.feedbackLink = new InternalLinkTypeEditProfileSettings(input); break;
					case InternalLinkTypeGame.CONSTRUCTOR: this.feedbackLink = new InternalLinkTypeGame(input); break;
					case InternalLinkTypeInstantView.CONSTRUCTOR: this.feedbackLink = new InternalLinkTypeInstantView(input); break;
					case InternalLinkTypeInvoice.CONSTRUCTOR: this.feedbackLink = new InternalLinkTypeInvoice(input); break;
					case InternalLinkTypeLanguagePack.CONSTRUCTOR: this.feedbackLink = new InternalLinkTypeLanguagePack(input); break;
					case InternalLinkTypeLanguageSettings.CONSTRUCTOR: this.feedbackLink = new InternalLinkTypeLanguageSettings(input); break;
					case InternalLinkTypeMessage.CONSTRUCTOR: this.feedbackLink = new InternalLinkTypeMessage(input); break;
					case InternalLinkTypeMessageDraft.CONSTRUCTOR: this.feedbackLink = new InternalLinkTypeMessageDraft(input); break;
					case InternalLinkTypePassportDataRequest.CONSTRUCTOR: this.feedbackLink = new InternalLinkTypePassportDataRequest(input); break;
					case InternalLinkTypePhoneNumberConfirmation.CONSTRUCTOR: this.feedbackLink = new InternalLinkTypePhoneNumberConfirmation(input); break;
					case InternalLinkTypePremiumFeatures.CONSTRUCTOR: this.feedbackLink = new InternalLinkTypePremiumFeatures(input); break;
					case InternalLinkTypePrivacyAndSecuritySettings.CONSTRUCTOR: this.feedbackLink = new InternalLinkTypePrivacyAndSecuritySettings(input); break;
					case InternalLinkTypeProxy.CONSTRUCTOR: this.feedbackLink = new InternalLinkTypeProxy(input); break;
					case InternalLinkTypePublicChat.CONSTRUCTOR: this.feedbackLink = new InternalLinkTypePublicChat(input); break;
					case InternalLinkTypeQrCodeAuthentication.CONSTRUCTOR: this.feedbackLink = new InternalLinkTypeQrCodeAuthentication(input); break;
					case InternalLinkTypeRestorePurchases.CONSTRUCTOR: this.feedbackLink = new InternalLinkTypeRestorePurchases(input); break;
					case InternalLinkTypeSettings.CONSTRUCTOR: this.feedbackLink = new InternalLinkTypeSettings(input); break;
					case InternalLinkTypeStickerSet.CONSTRUCTOR: this.feedbackLink = new InternalLinkTypeStickerSet(input); break;
					case InternalLinkTypeTheme.CONSTRUCTOR: this.feedbackLink = new InternalLinkTypeTheme(input); break;
					case InternalLinkTypeThemeSettings.CONSTRUCTOR: this.feedbackLink = new InternalLinkTypeThemeSettings(input); break;
					case InternalLinkTypeUnknownDeepLink.CONSTRUCTOR: this.feedbackLink = new InternalLinkTypeUnknownDeepLink(input); break;
					case InternalLinkTypeUnsupportedProxy.CONSTRUCTOR: this.feedbackLink = new InternalLinkTypeUnsupportedProxy(input); break;
					case InternalLinkTypeUserPhoneNumber.CONSTRUCTOR: this.feedbackLink = new InternalLinkTypeUserPhoneNumber(input); break;
					case InternalLinkTypeUserToken.CONSTRUCTOR: this.feedbackLink = new InternalLinkTypeUserToken(input); break;
					case InternalLinkTypeVideoChat.CONSTRUCTOR: this.feedbackLink = new InternalLinkTypeVideoChat(input); break;
					case InternalLinkTypeWebApp.CONSTRUCTOR: this.feedbackLink = new InternalLinkTypeWebApp(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return WebPageInstantView.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(WebPageInstantView.CONSTRUCTOR);
			if (this.pageBlocks == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.pageBlocks.length);
				for (int i = 0; i < this.pageBlocks.length; i++) {
					this.pageBlocks[i].serialize(output);
				}
			}
			output.writeInt(this.viewCount);
			output.writeInt(this.version);
			output.writeBoolean(this.isRtl);
			output.writeBoolean(this.isFull);
			if (this.feedbackLink == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.feedbackLink.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			WebPageInstantView webPageInstantView = (WebPageInstantView) o;
			if (!Arrays.equals(this.pageBlocks, webPageInstantView.pageBlocks)) {
				return false;
			}
			if (this.viewCount != webPageInstantView.viewCount) {
				return false;
			}
			if (this.version != webPageInstantView.version) {
				return false;
			}
			if (this.isRtl != webPageInstantView.isRtl) {
				return false;
			}
			if (this.isFull != webPageInstantView.isFull) {
				return false;
			}
			if (!Objects.equals(this.feedbackLink, webPageInstantView.feedbackLink)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.viewCount);
			result = result * 31 + (Arrays.hashCode(this.pageBlocks));
			result = result * 31 + (this.feedbackLink == null ? 0 : this.feedbackLink.hashCode());
			return result;
		}
	}

	/**
	 * Accepts an incoming call.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class AcceptCall extends Function<Ok> {


		/**
		 * Call identifier.
		**/
		public int callId;

		/**
		 * The call protocols supported by the application.
		**/
		public CallProtocol protocol;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -646618416;

		/**
		 * Accepts an incoming call.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public AcceptCall() {}

		/**
		 * Accepts an incoming call.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param callId Call identifier.
		 * @param protocol The call protocols supported by the application.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public AcceptCall(int callId, CallProtocol protocol) {
			this.callId = callId;
			this.protocol = protocol;
		}

		/**
		 * Accepts an incoming call.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AcceptCall(DataInput input) throws IOException {
			this.callId = input.readInt();
			if (input.readBoolean()) {
				if (CallProtocol.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.protocol = new CallProtocol(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AcceptCall.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AcceptCall.CONSTRUCTOR);
			output.writeInt(this.callId);
			if (this.protocol == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.protocol.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AcceptCall acceptCall = (AcceptCall) o;
			if (this.callId != acceptCall.callId) {
				return false;
			}
			if (!Objects.equals(this.protocol, acceptCall.protocol)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.callId);
			result = result * 31 + (this.protocol == null ? 0 : this.protocol.hashCode());
			return result;
		}
	}

	/**
	 * Accepts Telegram terms of services.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class AcceptTermsOfService extends Function<Ok> {


		/**
		 * Terms of service identifier.
		**/
		public String termsOfServiceId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2130576356;

		/**
		 * Accepts Telegram terms of services.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public AcceptTermsOfService() {}

		/**
		 * Accepts Telegram terms of services.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param termsOfServiceId Terms of service identifier.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public AcceptTermsOfService(String termsOfServiceId) {
			this.termsOfServiceId = termsOfServiceId;
		}

		/**
		 * Accepts Telegram terms of services.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AcceptTermsOfService(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] termsOfServiceIdTmp = new byte[input.readInt()];
				input.readFully(termsOfServiceIdTmp);
				this.termsOfServiceId = new String(termsOfServiceIdTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AcceptTermsOfService.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AcceptTermsOfService.CONSTRUCTOR);
			if (this.termsOfServiceId == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] termsOfServiceIdTmp = this.termsOfServiceId.getBytes(StandardCharsets.UTF_8);
				output.writeInt(termsOfServiceIdTmp.length);
				output.write(termsOfServiceIdTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AcceptTermsOfService acceptTermsOfService = (AcceptTermsOfService) o;
			if (this.termsOfServiceId != acceptTermsOfService.termsOfServiceId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.termsOfServiceId == null ? 0 : this.termsOfServiceId.hashCode();
		}
	}

	/**
	 * Adds server-provided application changelog as messages to the chat
	 * 777000 (Telegram); for official applications only. Returns a 404
	 * error if nothing changed.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class AddApplicationChangelog extends Function<Ok> {


		/**
		 * The previous application version.
		**/
		public String previousApplicationVersion;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1946976311;

		/**
		 * Adds server-provided application changelog as messages to the chat 777000 (Telegram); for official applications only. Returns a 404 error if nothing changed.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public AddApplicationChangelog() {}

		/**
		 * Adds server-provided application changelog as messages to the chat 777000 (Telegram); for official applications only. Returns a 404 error if nothing changed.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param previousApplicationVersion The previous application version.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public AddApplicationChangelog(String previousApplicationVersion) {
			this.previousApplicationVersion = previousApplicationVersion;
		}

		/**
		 * Adds server-provided application changelog as messages to the chat 777000 (Telegram); for official applications only. Returns a 404 error if nothing changed.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AddApplicationChangelog(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] previousApplicationVersionTmp = new byte[input.readInt()];
				input.readFully(previousApplicationVersionTmp);
				this.previousApplicationVersion = new String(previousApplicationVersionTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AddApplicationChangelog.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AddApplicationChangelog.CONSTRUCTOR);
			if (this.previousApplicationVersion == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] previousApplicationVersionTmp = this.previousApplicationVersion.getBytes(StandardCharsets.UTF_8);
				output.writeInt(previousApplicationVersionTmp.length);
				output.write(previousApplicationVersionTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AddApplicationChangelog addApplicationChangelog = (AddApplicationChangelog) o;
			if (this.previousApplicationVersion != addApplicationChangelog.previousApplicationVersion) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.previousApplicationVersion == null ? 0 : this.previousApplicationVersion.hashCode();
		}
	}

	/**
	 * Adds a chat folder by an invite link.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class AddChatFolderByInviteLink extends Function<Ok> {


		/**
		 * Invite link for the chat folder.
		**/
		public String inviteLink;

		/**
		 * Identifiers of the chats added to the chat folder. The chats are automatically joined if they aren&#039;t joined yet.
		**/
		public long[] chatIds;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -858593816;

		/**
		 * Adds a chat folder by an invite link.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public AddChatFolderByInviteLink() {}

		/**
		 * Adds a chat folder by an invite link.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param inviteLink Invite link for the chat folder.
		 * @param chatIds Identifiers of the chats added to the chat folder. The chats are automatically joined if they aren&#039;t joined yet.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public AddChatFolderByInviteLink(String inviteLink, long[] chatIds) {
			this.inviteLink = inviteLink;
			this.chatIds = chatIds;
		}

		/**
		 * Adds a chat folder by an invite link.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AddChatFolderByInviteLink(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] inviteLinkTmp = new byte[input.readInt()];
				input.readFully(inviteLinkTmp);
				this.inviteLink = new String(inviteLinkTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				this.chatIds = new long[input.readInt()];
				for (int i = 0; i < this.chatIds.length; i++) {
					this.chatIds[i] = input.readLong();
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AddChatFolderByInviteLink.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AddChatFolderByInviteLink.CONSTRUCTOR);
			if (this.inviteLink == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] inviteLinkTmp = this.inviteLink.getBytes(StandardCharsets.UTF_8);
				output.writeInt(inviteLinkTmp.length);
				output.write(inviteLinkTmp);
			}
			if (this.chatIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.chatIds.length);
				for (int i = 0; i < this.chatIds.length; i++) {
					output.writeLong(this.chatIds[i]);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AddChatFolderByInviteLink addChatFolderByInviteLink = (AddChatFolderByInviteLink) o;
			if (this.inviteLink != addChatFolderByInviteLink.inviteLink) {
				return false;
			}
			if (!Arrays.equals(this.chatIds, addChatFolderByInviteLink.chatIds)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.inviteLink == null ? 0 : this.inviteLink.hashCode();
			result = result * 31 + (Arrays.hashCode(this.chatIds));
			return result;
		}
	}

	/**
	 * Adds a new member to a chat. Members can&#039;t be added to private
	 * or secret chats.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class AddChatMember extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Identifier of the user.
		**/
		public long userId;

		/**
		 * The number of earlier messages from the chat to be forwarded to the new member; up to 100. Ignored for supergroups and channels, or if the added user is a bot.
		**/
		public int forwardLimit;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 499426810;

		/**
		 * Adds a new member to a chat. Members can&#039;t be added to private or secret chats.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public AddChatMember() {}

		/**
		 * Adds a new member to a chat. Members can&#039;t be added to private or secret chats.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param userId Identifier of the user.
		 * @param forwardLimit The number of earlier messages from the chat to be forwarded to the new member; up to 100. Ignored for supergroups and channels, or if the added user is a bot.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public AddChatMember(long chatId, long userId, int forwardLimit) {
			this.chatId = chatId;
			this.userId = userId;
			this.forwardLimit = forwardLimit;
		}

		/**
		 * Adds a new member to a chat. Members can&#039;t be added to private or secret chats.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AddChatMember(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.userId = input.readLong();
			this.forwardLimit = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AddChatMember.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AddChatMember.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.userId);
			output.writeInt(this.forwardLimit);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AddChatMember addChatMember = (AddChatMember) o;
			if (this.chatId != addChatMember.chatId) {
				return false;
			}
			if (this.userId != addChatMember.userId) {
				return false;
			}
			if (this.forwardLimit != addChatMember.forwardLimit) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Adds multiple new members to a chat. Currently, this method is only
	 * available for supergroups and channels. This method can&#039;t be
	 * used to join a chat. Members can&#039;t be added to a channel if it
	 * has more than 200 members.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class AddChatMembers extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Identifiers of the users to be added to the chat. The maximum number of added users is 20 for supergroups and 100 for channels.
		**/
		public long[] userIds;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -519951226;

		/**
		 * Adds multiple new members to a chat. Currently, this method is only available for supergroups and channels. This method can&#039;t be used to join a chat. Members can&#039;t be added to a channel if it has more than 200 members.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public AddChatMembers() {}

		/**
		 * Adds multiple new members to a chat. Currently, this method is only available for supergroups and channels. This method can&#039;t be used to join a chat. Members can&#039;t be added to a channel if it has more than 200 members.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param userIds Identifiers of the users to be added to the chat. The maximum number of added users is 20 for supergroups and 100 for channels.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public AddChatMembers(long chatId, long[] userIds) {
			this.chatId = chatId;
			this.userIds = userIds;
		}

		/**
		 * Adds multiple new members to a chat. Currently, this method is only available for supergroups and channels. This method can&#039;t be used to join a chat. Members can&#039;t be added to a channel if it has more than 200 members.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AddChatMembers(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				this.userIds = new long[input.readInt()];
				for (int i = 0; i < this.userIds.length; i++) {
					this.userIds[i] = input.readLong();
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AddChatMembers.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AddChatMembers.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.userIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.userIds.length);
				for (int i = 0; i < this.userIds.length; i++) {
					output.writeLong(this.userIds[i]);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AddChatMembers addChatMembers = (AddChatMembers) o;
			if (this.chatId != addChatMembers.chatId) {
				return false;
			}
			if (!Arrays.equals(this.userIds, addChatMembers.userIds)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (Arrays.hashCode(this.userIds));
			return result;
		}
	}

	/**
	 * Adds a chat to a chat list. A chat can&#039;t be simultaneously in
	 * Main and Archive chat lists, so it is automatically removed from
	 * another one if needed.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class AddChatToList extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * The chat list. Use getChatListsToAddChat to get suitable chat lists.
		**/
		public ChatList chatList;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -80523595;

		/**
		 * Adds a chat to a chat list. A chat can&#039;t be simultaneously in Main and Archive chat lists, so it is automatically removed from another one if needed.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public AddChatToList() {}

		/**
		 * Adds a chat to a chat list. A chat can&#039;t be simultaneously in Main and Archive chat lists, so it is automatically removed from another one if needed.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param chatList The chat list. Use getChatListsToAddChat to get suitable chat lists.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public AddChatToList(long chatId, ChatList chatList) {
			this.chatId = chatId;
			this.chatList = chatList;
		}

		/**
		 * Adds a chat to a chat list. A chat can&#039;t be simultaneously in Main and Archive chat lists, so it is automatically removed from another one if needed.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AddChatToList(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ChatListMain.CONSTRUCTOR: this.chatList = new ChatListMain(input); break;
					case ChatListArchive.CONSTRUCTOR: this.chatList = new ChatListArchive(input); break;
					case ChatListFolder.CONSTRUCTOR: this.chatList = new ChatListFolder(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AddChatToList.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AddChatToList.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.chatList == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.chatList.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AddChatToList addChatToList = (AddChatToList) o;
			if (this.chatId != addChatToList.chatId) {
				return false;
			}
			if (!Objects.equals(this.chatList, addChatToList.chatList)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.chatList == null ? 0 : this.chatList.hashCode());
			return result;
		}
	}

	/**
	 * Adds a user to the contact list or edits an existing contact by their
	 * user identifier.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class AddContact extends Function<Ok> {


		/**
		 * The contact to add or edit; phone number may be empty and needs to be specified only if known, vCard is ignored.
		**/
		public Contact contact;

		/**
		 * Pass true to share the current user&#039;s phone number with the new contact. A corresponding rule to userPrivacySettingShowPhoneNumber will be added if needed. Use the field userFullInfo.needPhoneNumberPrivacyException to check whether the current user needs to be asked to share their phone number.
		**/
		public boolean sharePhoneNumber;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1869640000;

		/**
		 * Adds a user to the contact list or edits an existing contact by their user identifier.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public AddContact() {}

		/**
		 * Adds a user to the contact list or edits an existing contact by their user identifier.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param contact The contact to add or edit; phone number may be empty and needs to be specified only if known, vCard is ignored.
		 * @param sharePhoneNumber Pass true to share the current user&#039;s phone number with the new contact. A corresponding rule to userPrivacySettingShowPhoneNumber will be added if needed. Use the field userFullInfo.needPhoneNumberPrivacyException to check whether the current user needs to be asked to share their phone number.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public AddContact(Contact contact, boolean sharePhoneNumber) {
			this.contact = contact;
			this.sharePhoneNumber = sharePhoneNumber;
		}

		/**
		 * Adds a user to the contact list or edits an existing contact by their user identifier.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AddContact(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Contact.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.contact = new Contact(input);
			}
			this.sharePhoneNumber = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AddContact.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AddContact.CONSTRUCTOR);
			if (this.contact == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.contact.serialize(output);
			}
			output.writeBoolean(this.sharePhoneNumber);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AddContact addContact = (AddContact) o;
			if (!Objects.equals(this.contact, addContact.contact)) {
				return false;
			}
			if (this.sharePhoneNumber != addContact.sharePhoneNumber) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.sharePhoneNumber);
			result = result * 31 + (this.contact == null ? 0 : this.contact.hashCode());
			return result;
		}
	}

	/**
	 * Adds a custom server language pack to the list of installed language
	 * packs in current localization target. Can be called before
	 * authorization.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class AddCustomServerLanguagePack extends Function<Ok> {


		/**
		 * Identifier of a language pack to be added.
		**/
		public String languagePackId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 4492771;

		/**
		 * Adds a custom server language pack to the list of installed language packs in current localization target. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public AddCustomServerLanguagePack() {}

		/**
		 * Adds a custom server language pack to the list of installed language packs in current localization target. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param languagePackId Identifier of a language pack to be added.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public AddCustomServerLanguagePack(String languagePackId) {
			this.languagePackId = languagePackId;
		}

		/**
		 * Adds a custom server language pack to the list of installed language packs in current localization target. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AddCustomServerLanguagePack(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] languagePackIdTmp = new byte[input.readInt()];
				input.readFully(languagePackIdTmp);
				this.languagePackId = new String(languagePackIdTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AddCustomServerLanguagePack.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AddCustomServerLanguagePack.CONSTRUCTOR);
			if (this.languagePackId == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] languagePackIdTmp = this.languagePackId.getBytes(StandardCharsets.UTF_8);
				output.writeInt(languagePackIdTmp.length);
				output.write(languagePackIdTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AddCustomServerLanguagePack addCustomServerLanguagePack = (AddCustomServerLanguagePack) o;
			if (this.languagePackId != addCustomServerLanguagePack.languagePackId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.languagePackId == null ? 0 : this.languagePackId.hashCode();
		}
	}

	/**
	 * Adds a new sticker to the list of favorite stickers. The new sticker
	 * is added to the top of the list. If the sticker was already in the
	 * list, it is removed from the list first. Only stickers belonging to a
	 * sticker set can be added to this list. Emoji stickers can&#039;t be
	 * added to favorite stickers.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class AddFavoriteSticker extends Function<Ok> {


		/**
		 * Sticker file to add.
		**/
		public InputFile sticker;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 324504799;

		/**
		 * Adds a new sticker to the list of favorite stickers. The new sticker is added to the top of the list. If the sticker was already in the list, it is removed from the list first. Only stickers belonging to a sticker set can be added to this list. Emoji stickers can&#039;t be added to favorite stickers.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public AddFavoriteSticker() {}

		/**
		 * Adds a new sticker to the list of favorite stickers. The new sticker is added to the top of the list. If the sticker was already in the list, it is removed from the list first. Only stickers belonging to a sticker set can be added to this list. Emoji stickers can&#039;t be added to favorite stickers.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param sticker Sticker file to add.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public AddFavoriteSticker(InputFile sticker) {
			this.sticker = sticker;
		}

		/**
		 * Adds a new sticker to the list of favorite stickers. The new sticker is added to the top of the list. If the sticker was already in the list, it is removed from the list first. Only stickers belonging to a sticker set can be added to this list. Emoji stickers can&#039;t be added to favorite stickers.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AddFavoriteSticker(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputFileId.CONSTRUCTOR: this.sticker = new InputFileId(input); break;
					case InputFileRemote.CONSTRUCTOR: this.sticker = new InputFileRemote(input); break;
					case InputFileLocal.CONSTRUCTOR: this.sticker = new InputFileLocal(input); break;
					case InputFileGenerated.CONSTRUCTOR: this.sticker = new InputFileGenerated(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AddFavoriteSticker.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AddFavoriteSticker.CONSTRUCTOR);
			if (this.sticker == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.sticker.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AddFavoriteSticker addFavoriteSticker = (AddFavoriteSticker) o;
			if (!Objects.equals(this.sticker, addFavoriteSticker.sticker)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.sticker == null ? 0 : this.sticker.hashCode();
		}
	}

	/**
	 * Adds a file from a message to the list of file downloads. Download
	 * progress and completion of the download will be notified through
	 * updateFile updates. If message database is used, the list of file
	 * downloads is persistent across application restarts. The downloading
	 * is independent from download using downloadFile, i.e. it continues if
	 * downloadFile is canceled or is used to download a part of the file.
	 * <p> Returns {@link File File} </p>
	**/
	public static final class AddFileToDownloads extends Function<File> {


		/**
		 * Identifier of the file to download.
		**/
		public int fileId;

		/**
		 * Chat identifier of the message with the file.
		**/
		public long chatId;

		/**
		 * Message identifier.
		**/
		public long messageId;

		/**
		 * Priority of the download (1-32). The higher the priority, the earlier the file will be downloaded. If the priorities of two files are equal, then the last one for which downloadFile/addFileToDownloads was called will be downloaded first.
		**/
		public int priority;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 867533751;

		/**
		 * Adds a file from a message to the list of file downloads. Download progress and completion of the download will be notified through updateFile updates. If message database is used, the list of file downloads is persistent across application restarts. The downloading is independent from download using downloadFile, i.e. it continues if downloadFile is canceled or is used to download a part of the file.
		 *
		 * <p> Returns {@link File File} </p>
		**/
		public AddFileToDownloads() {}

		/**
		 * Adds a file from a message to the list of file downloads. Download progress and completion of the download will be notified through updateFile updates. If message database is used, the list of file downloads is persistent across application restarts. The downloading is independent from download using downloadFile, i.e. it continues if downloadFile is canceled or is used to download a part of the file.
		 *
		 * <p> Returns {@link File File} </p>
		 *
		 * @param fileId Identifier of the file to download.
		 * @param chatId Chat identifier of the message with the file.
		 * @param messageId Message identifier.
		 * @param priority Priority of the download (1-32). The higher the priority, the earlier the file will be downloaded. If the priorities of two files are equal, then the last one for which downloadFile/addFileToDownloads was called will be downloaded first.
		 *
		 * <p> Returns {@link File File} </p>
		**/
		public AddFileToDownloads(int fileId, long chatId, long messageId, int priority) {
			this.fileId = fileId;
			this.chatId = chatId;
			this.messageId = messageId;
			this.priority = priority;
		}

		/**
		 * Adds a file from a message to the list of file downloads. Download progress and completion of the download will be notified through updateFile updates. If message database is used, the list of file downloads is persistent across application restarts. The downloading is independent from download using downloadFile, i.e. it continues if downloadFile is canceled or is used to download a part of the file.
		 *
		 * <p> Returns {@link File File} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AddFileToDownloads(DataInput input) throws IOException {
			this.fileId = input.readInt();
			this.chatId = input.readLong();
			this.messageId = input.readLong();
			this.priority = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AddFileToDownloads.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AddFileToDownloads.CONSTRUCTOR);
			output.writeInt(this.fileId);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
			output.writeInt(this.priority);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AddFileToDownloads addFileToDownloads = (AddFileToDownloads) o;
			if (this.fileId != addFileToDownloads.fileId) {
				return false;
			}
			if (this.chatId != addFileToDownloads.chatId) {
				return false;
			}
			if (this.messageId != addFileToDownloads.messageId) {
				return false;
			}
			if (this.priority != addFileToDownloads.priority) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.fileId);
			return result;
		}
	}

	/**
	 * Adds a local message to a chat. The message is persistent across
	 * application restarts only if the message database is used. Returns
	 * the added message.
	 * <p> Returns {@link Message Message} </p>
	**/
	public static final class AddLocalMessage extends Function<Message> {


		/**
		 * Target chat.
		**/
		public long chatId;

		/**
		 * Identifier of the sender of the message.
		**/
		public MessageSender senderId;

		/**
		 * Identifier of the replied message; 0 if none.
		**/
		public long replyToMessageId;

		/**
		 * Pass true to disable notification for the message.
		**/
		public boolean disableNotification;

		/**
		 * The content of the message to be added.
		**/
		public InputMessageContent inputMessageContent;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1998878725;

		/**
		 * Adds a local message to a chat. The message is persistent across application restarts only if the message database is used. Returns the added message.
		 *
		 * <p> Returns {@link Message Message} </p>
		**/
		public AddLocalMessage() {}

		/**
		 * Adds a local message to a chat. The message is persistent across application restarts only if the message database is used. Returns the added message.
		 *
		 * <p> Returns {@link Message Message} </p>
		 *
		 * @param chatId Target chat.
		 * @param senderId Identifier of the sender of the message.
		 * @param replyToMessageId Identifier of the replied message; 0 if none.
		 * @param disableNotification Pass true to disable notification for the message.
		 * @param inputMessageContent The content of the message to be added.
		 *
		 * <p> Returns {@link Message Message} </p>
		**/
		public AddLocalMessage(long chatId,
				MessageSender senderId,
				long replyToMessageId,
				boolean disableNotification,
				InputMessageContent inputMessageContent) {
			this.chatId = chatId;
			this.senderId = senderId;
			this.replyToMessageId = replyToMessageId;
			this.disableNotification = disableNotification;
			this.inputMessageContent = inputMessageContent;
		}

		/**
		 * Adds a local message to a chat. The message is persistent across application restarts only if the message database is used. Returns the added message.
		 *
		 * <p> Returns {@link Message Message} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AddLocalMessage(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case MessageSenderUser.CONSTRUCTOR: this.senderId = new MessageSenderUser(input); break;
					case MessageSenderChat.CONSTRUCTOR: this.senderId = new MessageSenderChat(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.replyToMessageId = input.readLong();
			this.disableNotification = input.readBoolean();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputMessageText.CONSTRUCTOR: this.inputMessageContent = new InputMessageText(input); break;
					case InputMessageAnimation.CONSTRUCTOR: this.inputMessageContent = new InputMessageAnimation(input); break;
					case InputMessageAudio.CONSTRUCTOR: this.inputMessageContent = new InputMessageAudio(input); break;
					case InputMessageDocument.CONSTRUCTOR: this.inputMessageContent = new InputMessageDocument(input); break;
					case InputMessagePhoto.CONSTRUCTOR: this.inputMessageContent = new InputMessagePhoto(input); break;
					case InputMessageSticker.CONSTRUCTOR: this.inputMessageContent = new InputMessageSticker(input); break;
					case InputMessageVideo.CONSTRUCTOR: this.inputMessageContent = new InputMessageVideo(input); break;
					case InputMessageVideoNote.CONSTRUCTOR: this.inputMessageContent = new InputMessageVideoNote(input); break;
					case InputMessageVoiceNote.CONSTRUCTOR: this.inputMessageContent = new InputMessageVoiceNote(input); break;
					case InputMessageLocation.CONSTRUCTOR: this.inputMessageContent = new InputMessageLocation(input); break;
					case InputMessageVenue.CONSTRUCTOR: this.inputMessageContent = new InputMessageVenue(input); break;
					case InputMessageContact.CONSTRUCTOR: this.inputMessageContent = new InputMessageContact(input); break;
					case InputMessageDice.CONSTRUCTOR: this.inputMessageContent = new InputMessageDice(input); break;
					case InputMessageGame.CONSTRUCTOR: this.inputMessageContent = new InputMessageGame(input); break;
					case InputMessageInvoice.CONSTRUCTOR: this.inputMessageContent = new InputMessageInvoice(input); break;
					case InputMessagePoll.CONSTRUCTOR: this.inputMessageContent = new InputMessagePoll(input); break;
					case InputMessageForwarded.CONSTRUCTOR: this.inputMessageContent = new InputMessageForwarded(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AddLocalMessage.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AddLocalMessage.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.senderId == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.senderId.serialize(output);
			}
			output.writeLong(this.replyToMessageId);
			output.writeBoolean(this.disableNotification);
			if (this.inputMessageContent == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.inputMessageContent.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AddLocalMessage addLocalMessage = (AddLocalMessage) o;
			if (this.chatId != addLocalMessage.chatId) {
				return false;
			}
			if (!Objects.equals(this.senderId, addLocalMessage.senderId)) {
				return false;
			}
			if (this.replyToMessageId != addLocalMessage.replyToMessageId) {
				return false;
			}
			if (this.disableNotification != addLocalMessage.disableNotification) {
				return false;
			}
			if (!Objects.equals(this.inputMessageContent, addLocalMessage.inputMessageContent)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.senderId == null ? 0 : this.senderId.hashCode());
			result = result * 31 + (this.inputMessageContent == null ? 0 : this.inputMessageContent.hashCode());
			return result;
		}
	}

	/**
	 * Adds a message to TDLib internal log. Can be called synchronously.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class AddLogMessage extends Function<Ok> {


		/**
		 * The minimum verbosity level needed for the message to be logged; 0-1023.
		**/
		public int verbosityLevel;

		/**
		 * Text of a message to log.
		**/
		public String text;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1597427692;

		/**
		 * Adds a message to TDLib internal log. Can be called synchronously.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public AddLogMessage() {}

		/**
		 * Adds a message to TDLib internal log. Can be called synchronously.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param verbosityLevel The minimum verbosity level needed for the message to be logged; 0-1023.
		 * @param text Text of a message to log.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public AddLogMessage(int verbosityLevel, String text) {
			this.verbosityLevel = verbosityLevel;
			this.text = text;
		}

		/**
		 * Adds a message to TDLib internal log. Can be called synchronously.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AddLogMessage(DataInput input) throws IOException {
			this.verbosityLevel = input.readInt();
			if (input.readBoolean()) {
				byte[] textTmp = new byte[input.readInt()];
				input.readFully(textTmp);
				this.text = new String(textTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AddLogMessage.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AddLogMessage.CONSTRUCTOR);
			output.writeInt(this.verbosityLevel);
			if (this.text == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] textTmp = this.text.getBytes(StandardCharsets.UTF_8);
				output.writeInt(textTmp.length);
				output.write(textTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AddLogMessage addLogMessage = (AddLogMessage) o;
			if (this.verbosityLevel != addLogMessage.verbosityLevel) {
				return false;
			}
			if (this.text != addLogMessage.text) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.verbosityLevel);
			result = result * 31 + (this.text == null ? 0 : this.text.hashCode());
			return result;
		}
	}

	/**
	 * Adds a reaction to a message. Use getMessageAvailableReactions to
	 * receive the list of available reactions for the message.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class AddMessageReaction extends Function<Ok> {


		/**
		 * Identifier of the chat to which the message belongs.
		**/
		public long chatId;

		/**
		 * Identifier of the message.
		**/
		public long messageId;

		/**
		 * Type of the reaction to add.
		**/
		public ReactionType reactionType;

		/**
		 * Pass true if the reaction is added with a big animation.
		**/
		public boolean isBig;

		/**
		 * Pass true if the reaction needs to be added to recent reactions.
		**/
		public boolean updateRecentReactions;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1419269613;

		/**
		 * Adds a reaction to a message. Use getMessageAvailableReactions to receive the list of available reactions for the message.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public AddMessageReaction() {}

		/**
		 * Adds a reaction to a message. Use getMessageAvailableReactions to receive the list of available reactions for the message.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Identifier of the chat to which the message belongs.
		 * @param messageId Identifier of the message.
		 * @param reactionType Type of the reaction to add.
		 * @param isBig Pass true if the reaction is added with a big animation.
		 * @param updateRecentReactions Pass true if the reaction needs to be added to recent reactions.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public AddMessageReaction(long chatId,
				long messageId,
				ReactionType reactionType,
				boolean isBig,
				boolean updateRecentReactions) {
			this.chatId = chatId;
			this.messageId = messageId;
			this.reactionType = reactionType;
			this.isBig = isBig;
			this.updateRecentReactions = updateRecentReactions;
		}

		/**
		 * Adds a reaction to a message. Use getMessageAvailableReactions to receive the list of available reactions for the message.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AddMessageReaction(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ReactionTypeEmoji.CONSTRUCTOR: this.reactionType = new ReactionTypeEmoji(input); break;
					case ReactionTypeCustomEmoji.CONSTRUCTOR: this.reactionType = new ReactionTypeCustomEmoji(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.isBig = input.readBoolean();
			this.updateRecentReactions = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AddMessageReaction.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AddMessageReaction.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
			if (this.reactionType == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.reactionType.serialize(output);
			}
			output.writeBoolean(this.isBig);
			output.writeBoolean(this.updateRecentReactions);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AddMessageReaction addMessageReaction = (AddMessageReaction) o;
			if (this.chatId != addMessageReaction.chatId) {
				return false;
			}
			if (this.messageId != addMessageReaction.messageId) {
				return false;
			}
			if (!Objects.equals(this.reactionType, addMessageReaction.reactionType)) {
				return false;
			}
			if (this.isBig != addMessageReaction.isBig) {
				return false;
			}
			if (this.updateRecentReactions != addMessageReaction.updateRecentReactions) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.reactionType == null ? 0 : this.reactionType.hashCode());
			return result;
		}
	}

	/**
	 * Adds the specified data to data usage statistics. Can be called
	 * before authorization.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class AddNetworkStatistics extends Function<Ok> {


		/**
		 * The network statistics entry with the data to be added to statistics.
		**/
		public NetworkStatisticsEntry entry;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1264825305;

		/**
		 * Adds the specified data to data usage statistics. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public AddNetworkStatistics() {}

		/**
		 * Adds the specified data to data usage statistics. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param entry The network statistics entry with the data to be added to statistics.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public AddNetworkStatistics(NetworkStatisticsEntry entry) {
			this.entry = entry;
		}

		/**
		 * Adds the specified data to data usage statistics. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AddNetworkStatistics(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case NetworkStatisticsEntryFile.CONSTRUCTOR: this.entry = new NetworkStatisticsEntryFile(input); break;
					case NetworkStatisticsEntryCall.CONSTRUCTOR: this.entry = new NetworkStatisticsEntryCall(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AddNetworkStatistics.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AddNetworkStatistics.CONSTRUCTOR);
			if (this.entry == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.entry.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AddNetworkStatistics addNetworkStatistics = (AddNetworkStatistics) o;
			if (!Objects.equals(this.entry, addNetworkStatistics.entry)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.entry == null ? 0 : this.entry.hashCode();
		}
	}

	/**
	 * Adds a proxy server for network requests. Can be called before
	 * authorization.
	 * <p> Returns {@link Proxy Proxy} </p>
	**/
	public static final class AddProxy extends Function<Proxy> {


		/**
		 * Proxy server IP address.
		**/
		public String server;

		/**
		 * Proxy server port.
		**/
		public int port;

		/**
		 * Pass true to immediately enable the proxy.
		**/
		public boolean enable;

		/**
		 * Proxy type.
		**/
		public ProxyType type;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 331529432;

		/**
		 * Adds a proxy server for network requests. Can be called before authorization.
		 *
		 * <p> Returns {@link Proxy Proxy} </p>
		**/
		public AddProxy() {}

		/**
		 * Adds a proxy server for network requests. Can be called before authorization.
		 *
		 * <p> Returns {@link Proxy Proxy} </p>
		 *
		 * @param server Proxy server IP address.
		 * @param port Proxy server port.
		 * @param enable Pass true to immediately enable the proxy.
		 * @param type Proxy type.
		 *
		 * <p> Returns {@link Proxy Proxy} </p>
		**/
		public AddProxy(String server, int port, boolean enable, ProxyType type) {
			this.server = server;
			this.port = port;
			this.enable = enable;
			this.type = type;
		}

		/**
		 * Adds a proxy server for network requests. Can be called before authorization.
		 *
		 * <p> Returns {@link Proxy Proxy} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AddProxy(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] serverTmp = new byte[input.readInt()];
				input.readFully(serverTmp);
				this.server = new String(serverTmp, StandardCharsets.UTF_8);
			}
			this.port = input.readInt();
			this.enable = input.readBoolean();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ProxyTypeSocks5.CONSTRUCTOR: this.type = new ProxyTypeSocks5(input); break;
					case ProxyTypeHttp.CONSTRUCTOR: this.type = new ProxyTypeHttp(input); break;
					case ProxyTypeMtproto.CONSTRUCTOR: this.type = new ProxyTypeMtproto(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AddProxy.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AddProxy.CONSTRUCTOR);
			if (this.server == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] serverTmp = this.server.getBytes(StandardCharsets.UTF_8);
				output.writeInt(serverTmp.length);
				output.write(serverTmp);
			}
			output.writeInt(this.port);
			output.writeBoolean(this.enable);
			if (this.type == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.type.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AddProxy addProxy = (AddProxy) o;
			if (this.server != addProxy.server) {
				return false;
			}
			if (this.port != addProxy.port) {
				return false;
			}
			if (this.enable != addProxy.enable) {
				return false;
			}
			if (!Objects.equals(this.type, addProxy.type)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.port);
			result = result * 31 + (this.server == null ? 0 : this.server.hashCode());
			result = result * 31 + (this.type == null ? 0 : this.type.hashCode());
			return result;
		}
	}

	/**
	 * Manually adds a new sticker to the list of recently used stickers.
	 * The new sticker is added to the top of the list. If the sticker was
	 * already in the list, it is removed from the list first. Only stickers
	 * belonging to a sticker set can be added to this list. Emoji stickers
	 * can&#039;t be added to recent stickers.
	 * <p> Returns {@link Stickers Stickers} </p>
	**/
	public static final class AddRecentSticker extends Function<Stickers> {


		/**
		 * Pass true to add the sticker to the list of stickers recently attached to photo or video files; pass false to add the sticker to the list of recently sent stickers.
		**/
		public boolean isAttached;

		/**
		 * Sticker file to add.
		**/
		public InputFile sticker;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1478109026;

		/**
		 * Manually adds a new sticker to the list of recently used stickers. The new sticker is added to the top of the list. If the sticker was already in the list, it is removed from the list first. Only stickers belonging to a sticker set can be added to this list. Emoji stickers can&#039;t be added to recent stickers.
		 *
		 * <p> Returns {@link Stickers Stickers} </p>
		**/
		public AddRecentSticker() {}

		/**
		 * Manually adds a new sticker to the list of recently used stickers. The new sticker is added to the top of the list. If the sticker was already in the list, it is removed from the list first. Only stickers belonging to a sticker set can be added to this list. Emoji stickers can&#039;t be added to recent stickers.
		 *
		 * <p> Returns {@link Stickers Stickers} </p>
		 *
		 * @param isAttached Pass true to add the sticker to the list of stickers recently attached to photo or video files; pass false to add the sticker to the list of recently sent stickers.
		 * @param sticker Sticker file to add.
		 *
		 * <p> Returns {@link Stickers Stickers} </p>
		**/
		public AddRecentSticker(boolean isAttached, InputFile sticker) {
			this.isAttached = isAttached;
			this.sticker = sticker;
		}

		/**
		 * Manually adds a new sticker to the list of recently used stickers. The new sticker is added to the top of the list. If the sticker was already in the list, it is removed from the list first. Only stickers belonging to a sticker set can be added to this list. Emoji stickers can&#039;t be added to recent stickers.
		 *
		 * <p> Returns {@link Stickers Stickers} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AddRecentSticker(DataInput input) throws IOException {
			this.isAttached = input.readBoolean();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputFileId.CONSTRUCTOR: this.sticker = new InputFileId(input); break;
					case InputFileRemote.CONSTRUCTOR: this.sticker = new InputFileRemote(input); break;
					case InputFileLocal.CONSTRUCTOR: this.sticker = new InputFileLocal(input); break;
					case InputFileGenerated.CONSTRUCTOR: this.sticker = new InputFileGenerated(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AddRecentSticker.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AddRecentSticker.CONSTRUCTOR);
			output.writeBoolean(this.isAttached);
			if (this.sticker == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.sticker.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AddRecentSticker addRecentSticker = (AddRecentSticker) o;
			if (this.isAttached != addRecentSticker.isAttached) {
				return false;
			}
			if (!Objects.equals(this.sticker, addRecentSticker.sticker)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isAttached);
			result = result * 31 + (this.sticker == null ? 0 : this.sticker.hashCode());
			return result;
		}
	}

	/**
	 * Adds a chat to the list of recently found chats. The chat is added to
	 * the beginning of the list. If the chat is already in the list, it
	 * will be removed from the list first.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class AddRecentlyFoundChat extends Function<Ok> {


		/**
		 * Identifier of the chat to add.
		**/
		public long chatId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1746396787;

		/**
		 * Adds a chat to the list of recently found chats. The chat is added to the beginning of the list. If the chat is already in the list, it will be removed from the list first.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public AddRecentlyFoundChat() {}

		/**
		 * Adds a chat to the list of recently found chats. The chat is added to the beginning of the list. If the chat is already in the list, it will be removed from the list first.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Identifier of the chat to add.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public AddRecentlyFoundChat(long chatId) {
			this.chatId = chatId;
		}

		/**
		 * Adds a chat to the list of recently found chats. The chat is added to the beginning of the list. If the chat is already in the list, it will be removed from the list first.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AddRecentlyFoundChat(DataInput input) throws IOException {
			this.chatId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AddRecentlyFoundChat.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AddRecentlyFoundChat.CONSTRUCTOR);
			output.writeLong(this.chatId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AddRecentlyFoundChat addRecentlyFoundChat = (AddRecentlyFoundChat) o;
			if (this.chatId != addRecentlyFoundChat.chatId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.chatId);
		}
	}

	/**
	 * Manually adds a new animation to the list of saved animations. The
	 * new animation is added to the beginning of the list. If the animation
	 * was already in the list, it is removed first. Only non-secret video
	 * animations with MIME type &quot;video/mp4&quot; can be added to the
	 * list.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class AddSavedAnimation extends Function<Ok> {


		/**
		 * The animation file to be added. Only animations known to the server (i.e., successfully sent via a message) can be added to the list.
		**/
		public InputFile animation;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1538525088;

		/**
		 * Manually adds a new animation to the list of saved animations. The new animation is added to the beginning of the list. If the animation was already in the list, it is removed first. Only non-secret video animations with MIME type &quot;video/mp4&quot; can be added to the list.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public AddSavedAnimation() {}

		/**
		 * Manually adds a new animation to the list of saved animations. The new animation is added to the beginning of the list. If the animation was already in the list, it is removed first. Only non-secret video animations with MIME type &quot;video/mp4&quot; can be added to the list.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param animation The animation file to be added. Only animations known to the server (i.e., successfully sent via a message) can be added to the list.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public AddSavedAnimation(InputFile animation) {
			this.animation = animation;
		}

		/**
		 * Manually adds a new animation to the list of saved animations. The new animation is added to the beginning of the list. If the animation was already in the list, it is removed first. Only non-secret video animations with MIME type &quot;video/mp4&quot; can be added to the list.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AddSavedAnimation(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputFileId.CONSTRUCTOR: this.animation = new InputFileId(input); break;
					case InputFileRemote.CONSTRUCTOR: this.animation = new InputFileRemote(input); break;
					case InputFileLocal.CONSTRUCTOR: this.animation = new InputFileLocal(input); break;
					case InputFileGenerated.CONSTRUCTOR: this.animation = new InputFileGenerated(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AddSavedAnimation.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AddSavedAnimation.CONSTRUCTOR);
			if (this.animation == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.animation.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AddSavedAnimation addSavedAnimation = (AddSavedAnimation) o;
			if (!Objects.equals(this.animation, addSavedAnimation.animation)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.animation == null ? 0 : this.animation.hashCode();
		}
	}

	/**
	 * Adds a new notification sound to the list of saved notification
	 * sounds. The new notification sound is added to the top of the list.
	 * If it is already in the list, its position isn&#039;t changed.
	 * <p> Returns {@link NotificationSound NotificationSound} </p>
	**/
	public static final class AddSavedNotificationSound extends Function<NotificationSound> {


		/**
		 * Notification sound file to add.
		**/
		public InputFile sound;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1043956975;

		/**
		 * Adds a new notification sound to the list of saved notification sounds. The new notification sound is added to the top of the list. If it is already in the list, its position isn&#039;t changed.
		 *
		 * <p> Returns {@link NotificationSound NotificationSound} </p>
		**/
		public AddSavedNotificationSound() {}

		/**
		 * Adds a new notification sound to the list of saved notification sounds. The new notification sound is added to the top of the list. If it is already in the list, its position isn&#039;t changed.
		 *
		 * <p> Returns {@link NotificationSound NotificationSound} </p>
		 *
		 * @param sound Notification sound file to add.
		 *
		 * <p> Returns {@link NotificationSound NotificationSound} </p>
		**/
		public AddSavedNotificationSound(InputFile sound) {
			this.sound = sound;
		}

		/**
		 * Adds a new notification sound to the list of saved notification sounds. The new notification sound is added to the top of the list. If it is already in the list, its position isn&#039;t changed.
		 *
		 * <p> Returns {@link NotificationSound NotificationSound} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AddSavedNotificationSound(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputFileId.CONSTRUCTOR: this.sound = new InputFileId(input); break;
					case InputFileRemote.CONSTRUCTOR: this.sound = new InputFileRemote(input); break;
					case InputFileLocal.CONSTRUCTOR: this.sound = new InputFileLocal(input); break;
					case InputFileGenerated.CONSTRUCTOR: this.sound = new InputFileGenerated(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AddSavedNotificationSound.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AddSavedNotificationSound.CONSTRUCTOR);
			if (this.sound == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.sound.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AddSavedNotificationSound addSavedNotificationSound = (AddSavedNotificationSound) o;
			if (!Objects.equals(this.sound, addSavedNotificationSound.sound)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.sound == null ? 0 : this.sound.hashCode();
		}
	}

	/**
	 * Adds a new sticker to a set; for bots only.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class AddStickerToSet extends Function<Ok> {


		/**
		 * Sticker set owner.
		**/
		public long userId;

		/**
		 * Sticker set name.
		**/
		public String name;

		/**
		 * Sticker to add to the set.
		**/
		public InputSticker sticker;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1457266235;

		/**
		 * Adds a new sticker to a set; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public AddStickerToSet() {}

		/**
		 * Adds a new sticker to a set; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param userId Sticker set owner.
		 * @param name Sticker set name.
		 * @param sticker Sticker to add to the set.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public AddStickerToSet(long userId, String name, InputSticker sticker) {
			this.userId = userId;
			this.name = name;
			this.sticker = sticker;
		}

		/**
		 * Adds a new sticker to a set; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AddStickerToSet(DataInput input) throws IOException {
			this.userId = input.readLong();
			if (input.readBoolean()) {
				byte[] nameTmp = new byte[input.readInt()];
				input.readFully(nameTmp);
				this.name = new String(nameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (InputSticker.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.sticker = new InputSticker(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AddStickerToSet.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AddStickerToSet.CONSTRUCTOR);
			output.writeLong(this.userId);
			if (this.name == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nameTmp = this.name.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nameTmp.length);
				output.write(nameTmp);
			}
			if (this.sticker == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.sticker.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AddStickerToSet addStickerToSet = (AddStickerToSet) o;
			if (this.userId != addStickerToSet.userId) {
				return false;
			}
			if (this.name != addStickerToSet.name) {
				return false;
			}
			if (!Objects.equals(this.sticker, addStickerToSet.sticker)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.userId);
			result = result * 31 + (this.name == null ? 0 : this.name.hashCode());
			result = result * 31 + (this.sticker == null ? 0 : this.sticker.hashCode());
			return result;
		}
	}

	/**
	 * Sets the result of a callback query; for bots only.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class AnswerCallbackQuery extends Function<Ok> {


		/**
		 * Identifier of the callback query.
		**/
		public long callbackQueryId;

		/**
		 * Text of the answer.
		**/
		public String text;

		/**
		 * Pass true to show an alert to the user instead of a toast notification.
		**/
		public boolean showAlert;

		/**
		 * URL to be opened.
		**/
		public String url;

		/**
		 * Time during which the result of the query can be cached, in seconds.
		**/
		public int cacheTime;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1153028490;

		/**
		 * Sets the result of a callback query; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public AnswerCallbackQuery() {}

		/**
		 * Sets the result of a callback query; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param callbackQueryId Identifier of the callback query.
		 * @param text Text of the answer.
		 * @param showAlert Pass true to show an alert to the user instead of a toast notification.
		 * @param url URL to be opened.
		 * @param cacheTime Time during which the result of the query can be cached, in seconds.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public AnswerCallbackQuery(long callbackQueryId,
				String text,
				boolean showAlert,
				String url,
				int cacheTime) {
			this.callbackQueryId = callbackQueryId;
			this.text = text;
			this.showAlert = showAlert;
			this.url = url;
			this.cacheTime = cacheTime;
		}

		/**
		 * Sets the result of a callback query; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AnswerCallbackQuery(DataInput input) throws IOException {
			this.callbackQueryId = input.readLong();
			if (input.readBoolean()) {
				byte[] textTmp = new byte[input.readInt()];
				input.readFully(textTmp);
				this.text = new String(textTmp, StandardCharsets.UTF_8);
			}
			this.showAlert = input.readBoolean();
			if (input.readBoolean()) {
				byte[] urlTmp = new byte[input.readInt()];
				input.readFully(urlTmp);
				this.url = new String(urlTmp, StandardCharsets.UTF_8);
			}
			this.cacheTime = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AnswerCallbackQuery.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AnswerCallbackQuery.CONSTRUCTOR);
			output.writeLong(this.callbackQueryId);
			if (this.text == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] textTmp = this.text.getBytes(StandardCharsets.UTF_8);
				output.writeInt(textTmp.length);
				output.write(textTmp);
			}
			output.writeBoolean(this.showAlert);
			if (this.url == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] urlTmp = this.url.getBytes(StandardCharsets.UTF_8);
				output.writeInt(urlTmp.length);
				output.write(urlTmp);
			}
			output.writeInt(this.cacheTime);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AnswerCallbackQuery answerCallbackQuery = (AnswerCallbackQuery) o;
			if (this.callbackQueryId != answerCallbackQuery.callbackQueryId) {
				return false;
			}
			if (this.text != answerCallbackQuery.text) {
				return false;
			}
			if (this.showAlert != answerCallbackQuery.showAlert) {
				return false;
			}
			if (this.url != answerCallbackQuery.url) {
				return false;
			}
			if (this.cacheTime != answerCallbackQuery.cacheTime) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.callbackQueryId);
			result = result * 31 + (this.text == null ? 0 : this.text.hashCode());
			result = result * 31 + (this.url == null ? 0 : this.url.hashCode());
			return result;
		}
	}

	/**
	 * Answers a custom query; for bots only.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class AnswerCustomQuery extends Function<Ok> {


		/**
		 * Identifier of a custom query.
		**/
		public long customQueryId;

		/**
		 * JSON-serialized answer to the query.
		**/
		public String data;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1293603521;

		/**
		 * Answers a custom query; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public AnswerCustomQuery() {}

		/**
		 * Answers a custom query; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param customQueryId Identifier of a custom query.
		 * @param data JSON-serialized answer to the query.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public AnswerCustomQuery(long customQueryId, String data) {
			this.customQueryId = customQueryId;
			this.data = data;
		}

		/**
		 * Answers a custom query; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AnswerCustomQuery(DataInput input) throws IOException {
			this.customQueryId = input.readLong();
			if (input.readBoolean()) {
				byte[] dataTmp = new byte[input.readInt()];
				input.readFully(dataTmp);
				this.data = new String(dataTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AnswerCustomQuery.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AnswerCustomQuery.CONSTRUCTOR);
			output.writeLong(this.customQueryId);
			if (this.data == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] dataTmp = this.data.getBytes(StandardCharsets.UTF_8);
				output.writeInt(dataTmp.length);
				output.write(dataTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AnswerCustomQuery answerCustomQuery = (AnswerCustomQuery) o;
			if (this.customQueryId != answerCustomQuery.customQueryId) {
				return false;
			}
			if (this.data != answerCustomQuery.data) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.customQueryId);
			result = result * 31 + (this.data == null ? 0 : this.data.hashCode());
			return result;
		}
	}

	/**
	 * Sets the result of an inline query; for bots only.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class AnswerInlineQuery extends Function<Ok> {


		/**
		 * Identifier of the inline query.
		**/
		public long inlineQueryId;

		/**
		 * Pass true if results may be cached and returned only for the user that sent the query. By default, results may be returned to any user who sends the same query.
		**/
		public boolean isPersonal;

		/**
		 * Button to be shown above inline query results; pass null if none.
		**/
		public InlineQueryResultsButton button;

		/**
		 * The results of the query.
		**/
		public InputInlineQueryResult[] results;

		/**
		 * Allowed time to cache the results of the query, in seconds.
		**/
		public int cacheTime;

		/**
		 * Offset for the next inline query; pass an empty string if there are no more results.
		**/
		public String nextOffset;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1343853844;

		/**
		 * Sets the result of an inline query; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public AnswerInlineQuery() {}

		/**
		 * Sets the result of an inline query; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param inlineQueryId Identifier of the inline query.
		 * @param isPersonal Pass true if results may be cached and returned only for the user that sent the query. By default, results may be returned to any user who sends the same query.
		 * @param button Button to be shown above inline query results; pass null if none.
		 * @param results The results of the query.
		 * @param cacheTime Allowed time to cache the results of the query, in seconds.
		 * @param nextOffset Offset for the next inline query; pass an empty string if there are no more results.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public AnswerInlineQuery(long inlineQueryId,
				boolean isPersonal,
				InlineQueryResultsButton button,
				InputInlineQueryResult[] results,
				int cacheTime,
				String nextOffset) {
			this.inlineQueryId = inlineQueryId;
			this.isPersonal = isPersonal;
			this.button = button;
			this.results = results;
			this.cacheTime = cacheTime;
			this.nextOffset = nextOffset;
		}

		/**
		 * Sets the result of an inline query; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AnswerInlineQuery(DataInput input) throws IOException {
			this.inlineQueryId = input.readLong();
			this.isPersonal = input.readBoolean();
			if (input.readBoolean()) {
				if (InlineQueryResultsButton.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.button = new InlineQueryResultsButton(input);
			}
			if (input.readBoolean()) {
				this.results = new InputInlineQueryResult[input.readInt()];
				for (int i = 0; i < this.results.length; i++) {
					switch(input.readInt()) {
						case InputInlineQueryResultAnimation.CONSTRUCTOR: this.results[i] = new InputInlineQueryResultAnimation(input); break;
						case InputInlineQueryResultArticle.CONSTRUCTOR: this.results[i] = new InputInlineQueryResultArticle(input); break;
						case InputInlineQueryResultAudio.CONSTRUCTOR: this.results[i] = new InputInlineQueryResultAudio(input); break;
						case InputInlineQueryResultContact.CONSTRUCTOR: this.results[i] = new InputInlineQueryResultContact(input); break;
						case InputInlineQueryResultDocument.CONSTRUCTOR: this.results[i] = new InputInlineQueryResultDocument(input); break;
						case InputInlineQueryResultGame.CONSTRUCTOR: this.results[i] = new InputInlineQueryResultGame(input); break;
						case InputInlineQueryResultLocation.CONSTRUCTOR: this.results[i] = new InputInlineQueryResultLocation(input); break;
						case InputInlineQueryResultPhoto.CONSTRUCTOR: this.results[i] = new InputInlineQueryResultPhoto(input); break;
						case InputInlineQueryResultSticker.CONSTRUCTOR: this.results[i] = new InputInlineQueryResultSticker(input); break;
						case InputInlineQueryResultVenue.CONSTRUCTOR: this.results[i] = new InputInlineQueryResultVenue(input); break;
						case InputInlineQueryResultVideo.CONSTRUCTOR: this.results[i] = new InputInlineQueryResultVideo(input); break;
						case InputInlineQueryResultVoiceNote.CONSTRUCTOR: this.results[i] = new InputInlineQueryResultVoiceNote(input); break;
						default: {
							throw new UnsupportedOperationException();
						}
					}
				}
			}
			this.cacheTime = input.readInt();
			if (input.readBoolean()) {
				byte[] nextOffsetTmp = new byte[input.readInt()];
				input.readFully(nextOffsetTmp);
				this.nextOffset = new String(nextOffsetTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AnswerInlineQuery.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AnswerInlineQuery.CONSTRUCTOR);
			output.writeLong(this.inlineQueryId);
			output.writeBoolean(this.isPersonal);
			if (this.button == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.button.serialize(output);
			}
			if (this.results == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.results.length);
				for (int i = 0; i < this.results.length; i++) {
					this.results[i].serialize(output);
				}
			}
			output.writeInt(this.cacheTime);
			if (this.nextOffset == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nextOffsetTmp = this.nextOffset.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nextOffsetTmp.length);
				output.write(nextOffsetTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AnswerInlineQuery answerInlineQuery = (AnswerInlineQuery) o;
			if (this.inlineQueryId != answerInlineQuery.inlineQueryId) {
				return false;
			}
			if (this.isPersonal != answerInlineQuery.isPersonal) {
				return false;
			}
			if (!Objects.equals(this.button, answerInlineQuery.button)) {
				return false;
			}
			if (!Arrays.equals(this.results, answerInlineQuery.results)) {
				return false;
			}
			if (this.cacheTime != answerInlineQuery.cacheTime) {
				return false;
			}
			if (this.nextOffset != answerInlineQuery.nextOffset) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.inlineQueryId);
			result = result * 31 + (this.button == null ? 0 : this.button.hashCode());
			result = result * 31 + (Arrays.hashCode(this.results));
			result = result * 31 + (this.nextOffset == null ? 0 : this.nextOffset.hashCode());
			return result;
		}
	}

	/**
	 * Sets the result of a pre-checkout query; for bots only.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class AnswerPreCheckoutQuery extends Function<Ok> {


		/**
		 * Identifier of the pre-checkout query.
		**/
		public long preCheckoutQueryId;

		/**
		 * An error message, empty on success.
		**/
		public String errorMessage;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1486789653;

		/**
		 * Sets the result of a pre-checkout query; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public AnswerPreCheckoutQuery() {}

		/**
		 * Sets the result of a pre-checkout query; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param preCheckoutQueryId Identifier of the pre-checkout query.
		 * @param errorMessage An error message, empty on success.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public AnswerPreCheckoutQuery(long preCheckoutQueryId, String errorMessage) {
			this.preCheckoutQueryId = preCheckoutQueryId;
			this.errorMessage = errorMessage;
		}

		/**
		 * Sets the result of a pre-checkout query; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AnswerPreCheckoutQuery(DataInput input) throws IOException {
			this.preCheckoutQueryId = input.readLong();
			if (input.readBoolean()) {
				byte[] errorMessageTmp = new byte[input.readInt()];
				input.readFully(errorMessageTmp);
				this.errorMessage = new String(errorMessageTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AnswerPreCheckoutQuery.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AnswerPreCheckoutQuery.CONSTRUCTOR);
			output.writeLong(this.preCheckoutQueryId);
			if (this.errorMessage == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] errorMessageTmp = this.errorMessage.getBytes(StandardCharsets.UTF_8);
				output.writeInt(errorMessageTmp.length);
				output.write(errorMessageTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AnswerPreCheckoutQuery answerPreCheckoutQuery = (AnswerPreCheckoutQuery) o;
			if (this.preCheckoutQueryId != answerPreCheckoutQuery.preCheckoutQueryId) {
				return false;
			}
			if (this.errorMessage != answerPreCheckoutQuery.errorMessage) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.preCheckoutQueryId);
			result = result * 31 + (this.errorMessage == null ? 0 : this.errorMessage.hashCode());
			return result;
		}
	}

	/**
	 * Sets the result of a shipping query; for bots only.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class AnswerShippingQuery extends Function<Ok> {


		/**
		 * Identifier of the shipping query.
		**/
		public long shippingQueryId;

		/**
		 * Available shipping options.
		**/
		public ShippingOption[] shippingOptions;

		/**
		 * An error message, empty on success.
		**/
		public String errorMessage;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -434601324;

		/**
		 * Sets the result of a shipping query; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public AnswerShippingQuery() {}

		/**
		 * Sets the result of a shipping query; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param shippingQueryId Identifier of the shipping query.
		 * @param shippingOptions Available shipping options.
		 * @param errorMessage An error message, empty on success.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public AnswerShippingQuery(long shippingQueryId,
				ShippingOption[] shippingOptions,
				String errorMessage) {
			this.shippingQueryId = shippingQueryId;
			this.shippingOptions = shippingOptions;
			this.errorMessage = errorMessage;
		}

		/**
		 * Sets the result of a shipping query; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AnswerShippingQuery(DataInput input) throws IOException {
			this.shippingQueryId = input.readLong();
			if (input.readBoolean()) {
				this.shippingOptions = new ShippingOption[input.readInt()];
				for (int i = 0; i < this.shippingOptions.length; i++) {
					if (ShippingOption.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.shippingOptions[i] = new ShippingOption(input);
				}
			}
			if (input.readBoolean()) {
				byte[] errorMessageTmp = new byte[input.readInt()];
				input.readFully(errorMessageTmp);
				this.errorMessage = new String(errorMessageTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AnswerShippingQuery.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AnswerShippingQuery.CONSTRUCTOR);
			output.writeLong(this.shippingQueryId);
			if (this.shippingOptions == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.shippingOptions.length);
				for (int i = 0; i < this.shippingOptions.length; i++) {
					this.shippingOptions[i].serialize(output);
				}
			}
			if (this.errorMessage == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] errorMessageTmp = this.errorMessage.getBytes(StandardCharsets.UTF_8);
				output.writeInt(errorMessageTmp.length);
				output.write(errorMessageTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AnswerShippingQuery answerShippingQuery = (AnswerShippingQuery) o;
			if (this.shippingQueryId != answerShippingQuery.shippingQueryId) {
				return false;
			}
			if (!Arrays.equals(this.shippingOptions, answerShippingQuery.shippingOptions)) {
				return false;
			}
			if (this.errorMessage != answerShippingQuery.errorMessage) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.shippingQueryId);
			result = result * 31 + (Arrays.hashCode(this.shippingOptions));
			result = result * 31 + (this.errorMessage == null ? 0 : this.errorMessage.hashCode());
			return result;
		}
	}

	/**
	 * Sets the result of interaction with a Web App and sends corresponding
	 * message on behalf of the user to the chat from which the query
	 * originated; for bots only.
	 * <p> Returns {@link SentWebAppMessage SentWebAppMessage} </p>
	**/
	public static final class AnswerWebAppQuery extends Function<SentWebAppMessage> {


		/**
		 * Identifier of the Web App query.
		**/
		public String webAppQueryId;

		/**
		 * The result of the query.
		**/
		public InputInlineQueryResult result;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1598776079;

		/**
		 * Sets the result of interaction with a Web App and sends corresponding message on behalf of the user to the chat from which the query originated; for bots only.
		 *
		 * <p> Returns {@link SentWebAppMessage SentWebAppMessage} </p>
		**/
		public AnswerWebAppQuery() {}

		/**
		 * Sets the result of interaction with a Web App and sends corresponding message on behalf of the user to the chat from which the query originated; for bots only.
		 *
		 * <p> Returns {@link SentWebAppMessage SentWebAppMessage} </p>
		 *
		 * @param webAppQueryId Identifier of the Web App query.
		 * @param result The result of the query.
		 *
		 * <p> Returns {@link SentWebAppMessage SentWebAppMessage} </p>
		**/
		public AnswerWebAppQuery(String webAppQueryId, InputInlineQueryResult result) {
			this.webAppQueryId = webAppQueryId;
			this.result = result;
		}

		/**
		 * Sets the result of interaction with a Web App and sends corresponding message on behalf of the user to the chat from which the query originated; for bots only.
		 *
		 * <p> Returns {@link SentWebAppMessage SentWebAppMessage} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AnswerWebAppQuery(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] webAppQueryIdTmp = new byte[input.readInt()];
				input.readFully(webAppQueryIdTmp);
				this.webAppQueryId = new String(webAppQueryIdTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputInlineQueryResultAnimation.CONSTRUCTOR: this.result = new InputInlineQueryResultAnimation(input); break;
					case InputInlineQueryResultArticle.CONSTRUCTOR: this.result = new InputInlineQueryResultArticle(input); break;
					case InputInlineQueryResultAudio.CONSTRUCTOR: this.result = new InputInlineQueryResultAudio(input); break;
					case InputInlineQueryResultContact.CONSTRUCTOR: this.result = new InputInlineQueryResultContact(input); break;
					case InputInlineQueryResultDocument.CONSTRUCTOR: this.result = new InputInlineQueryResultDocument(input); break;
					case InputInlineQueryResultGame.CONSTRUCTOR: this.result = new InputInlineQueryResultGame(input); break;
					case InputInlineQueryResultLocation.CONSTRUCTOR: this.result = new InputInlineQueryResultLocation(input); break;
					case InputInlineQueryResultPhoto.CONSTRUCTOR: this.result = new InputInlineQueryResultPhoto(input); break;
					case InputInlineQueryResultSticker.CONSTRUCTOR: this.result = new InputInlineQueryResultSticker(input); break;
					case InputInlineQueryResultVenue.CONSTRUCTOR: this.result = new InputInlineQueryResultVenue(input); break;
					case InputInlineQueryResultVideo.CONSTRUCTOR: this.result = new InputInlineQueryResultVideo(input); break;
					case InputInlineQueryResultVoiceNote.CONSTRUCTOR: this.result = new InputInlineQueryResultVoiceNote(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AnswerWebAppQuery.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AnswerWebAppQuery.CONSTRUCTOR);
			if (this.webAppQueryId == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] webAppQueryIdTmp = this.webAppQueryId.getBytes(StandardCharsets.UTF_8);
				output.writeInt(webAppQueryIdTmp.length);
				output.write(webAppQueryIdTmp);
			}
			if (this.result == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.result.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AnswerWebAppQuery answerWebAppQuery = (AnswerWebAppQuery) o;
			if (this.webAppQueryId != answerWebAppQuery.webAppQueryId) {
				return false;
			}
			if (!Objects.equals(this.result, answerWebAppQuery.result)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.webAppQueryId == null ? 0 : this.webAppQueryId.hashCode();
			result = result * 31 + (this.result == null ? 0 : this.result.hashCode());
			return result;
		}
	}

	/**
	 * Informs server about a purchase through App Store. For official
	 * applications only.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class AssignAppStoreTransaction extends Function<Ok> {


		/**
		 * App Store receipt.
		**/
		public byte[] receipt;

		/**
		 * Transaction purpose.
		**/
		public StorePaymentPurpose purpose;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2030892112;

		/**
		 * Informs server about a purchase through App Store. For official applications only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public AssignAppStoreTransaction() {}

		/**
		 * Informs server about a purchase through App Store. For official applications only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param receipt App Store receipt.
		 * @param purpose Transaction purpose.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public AssignAppStoreTransaction(byte[] receipt, StorePaymentPurpose purpose) {
			this.receipt = receipt;
			this.purpose = purpose;
		}

		/**
		 * Informs server about a purchase through App Store. For official applications only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AssignAppStoreTransaction(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.receipt = new byte[input.readInt()];
				input.readFully(this.receipt);
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case StorePaymentPurposePremiumSubscription.CONSTRUCTOR: this.purpose = new StorePaymentPurposePremiumSubscription(input); break;
					case StorePaymentPurposeGiftedPremium.CONSTRUCTOR: this.purpose = new StorePaymentPurposeGiftedPremium(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AssignAppStoreTransaction.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AssignAppStoreTransaction.CONSTRUCTOR);
			if (this.receipt == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.receipt.length);
				output.write(this.receipt);
			}
			if (this.purpose == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.purpose.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AssignAppStoreTransaction assignAppStoreTransaction = (AssignAppStoreTransaction) o;
			if (this.receipt != assignAppStoreTransaction.receipt) {
				return false;
			}
			if (!Objects.equals(this.purpose, assignAppStoreTransaction.purpose)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Arrays.hashCode(this.receipt);
			result = result * 31 + (this.purpose == null ? 0 : this.purpose.hashCode());
			return result;
		}
	}

	/**
	 * Informs server about a purchase through Google Play. For official
	 * applications only.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class AssignGooglePlayTransaction extends Function<Ok> {


		/**
		 * Application package name.
		**/
		public String packageName;

		/**
		 * Identifier of the purchased store product.
		**/
		public String storeProductId;

		/**
		 * Google Play purchase token.
		**/
		public String purchaseToken;

		/**
		 * Transaction purpose.
		**/
		public StorePaymentPurpose purpose;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1992704860;

		/**
		 * Informs server about a purchase through Google Play. For official applications only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public AssignGooglePlayTransaction() {}

		/**
		 * Informs server about a purchase through Google Play. For official applications only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param packageName Application package name.
		 * @param storeProductId Identifier of the purchased store product.
		 * @param purchaseToken Google Play purchase token.
		 * @param purpose Transaction purpose.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public AssignGooglePlayTransaction(String packageName,
				String storeProductId,
				String purchaseToken,
				StorePaymentPurpose purpose) {
			this.packageName = packageName;
			this.storeProductId = storeProductId;
			this.purchaseToken = purchaseToken;
			this.purpose = purpose;
		}

		/**
		 * Informs server about a purchase through Google Play. For official applications only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public AssignGooglePlayTransaction(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] packageNameTmp = new byte[input.readInt()];
				input.readFully(packageNameTmp);
				this.packageName = new String(packageNameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] storeProductIdTmp = new byte[input.readInt()];
				input.readFully(storeProductIdTmp);
				this.storeProductId = new String(storeProductIdTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] purchaseTokenTmp = new byte[input.readInt()];
				input.readFully(purchaseTokenTmp);
				this.purchaseToken = new String(purchaseTokenTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case StorePaymentPurposePremiumSubscription.CONSTRUCTOR: this.purpose = new StorePaymentPurposePremiumSubscription(input); break;
					case StorePaymentPurposeGiftedPremium.CONSTRUCTOR: this.purpose = new StorePaymentPurposeGiftedPremium(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return AssignGooglePlayTransaction.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(AssignGooglePlayTransaction.CONSTRUCTOR);
			if (this.packageName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] packageNameTmp = this.packageName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(packageNameTmp.length);
				output.write(packageNameTmp);
			}
			if (this.storeProductId == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] storeProductIdTmp = this.storeProductId.getBytes(StandardCharsets.UTF_8);
				output.writeInt(storeProductIdTmp.length);
				output.write(storeProductIdTmp);
			}
			if (this.purchaseToken == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] purchaseTokenTmp = this.purchaseToken.getBytes(StandardCharsets.UTF_8);
				output.writeInt(purchaseTokenTmp.length);
				output.write(purchaseTokenTmp);
			}
			if (this.purpose == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.purpose.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			AssignGooglePlayTransaction assignGooglePlayTransaction = (AssignGooglePlayTransaction) o;
			if (this.packageName != assignGooglePlayTransaction.packageName) {
				return false;
			}
			if (this.storeProductId != assignGooglePlayTransaction.storeProductId) {
				return false;
			}
			if (this.purchaseToken != assignGooglePlayTransaction.purchaseToken) {
				return false;
			}
			if (!Objects.equals(this.purpose, assignGooglePlayTransaction.purpose)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.packageName == null ? 0 : this.packageName.hashCode();
			result = result * 31 + (this.storeProductId == null ? 0 : this.storeProductId.hashCode());
			result = result * 31 + (this.purchaseToken == null ? 0 : this.purchaseToken.hashCode());
			result = result * 31 + (this.purpose == null ? 0 : this.purpose.hashCode());
			return result;
		}
	}

	/**
	 * Bans a member in a chat. Members can&#039;t be banned in private or
	 * secret chats. In supergroups and channels, the user will not be able
	 * to return to the group on their own using invite links, etc., unless
	 * unbanned first.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class BanChatMember extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Member identifier.
		**/
		public MessageSender memberId;

		/**
		 * Point in time (Unix timestamp) when the user will be unbanned; 0 if never. If the user is banned for more than 366 days or for less than 30 seconds from the current time, the user is considered to be banned forever. Ignored in basic groups and if a chat is banned.
		**/
		public int bannedUntilDate;

		/**
		 * Pass true to delete all messages in the chat for the user that is being removed. Always true for supergroups and channels.
		**/
		public boolean revokeMessages;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -888111748;

		/**
		 * Bans a member in a chat. Members can&#039;t be banned in private or secret chats. In supergroups and channels, the user will not be able to return to the group on their own using invite links, etc., unless unbanned first.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public BanChatMember() {}

		/**
		 * Bans a member in a chat. Members can&#039;t be banned in private or secret chats. In supergroups and channels, the user will not be able to return to the group on their own using invite links, etc., unless unbanned first.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param memberId Member identifier.
		 * @param bannedUntilDate Point in time (Unix timestamp) when the user will be unbanned; 0 if never. If the user is banned for more than 366 days or for less than 30 seconds from the current time, the user is considered to be banned forever. Ignored in basic groups and if a chat is banned.
		 * @param revokeMessages Pass true to delete all messages in the chat for the user that is being removed. Always true for supergroups and channels.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public BanChatMember(long chatId,
				MessageSender memberId,
				int bannedUntilDate,
				boolean revokeMessages) {
			this.chatId = chatId;
			this.memberId = memberId;
			this.bannedUntilDate = bannedUntilDate;
			this.revokeMessages = revokeMessages;
		}

		/**
		 * Bans a member in a chat. Members can&#039;t be banned in private or secret chats. In supergroups and channels, the user will not be able to return to the group on their own using invite links, etc., unless unbanned first.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public BanChatMember(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case MessageSenderUser.CONSTRUCTOR: this.memberId = new MessageSenderUser(input); break;
					case MessageSenderChat.CONSTRUCTOR: this.memberId = new MessageSenderChat(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.bannedUntilDate = input.readInt();
			this.revokeMessages = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return BanChatMember.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(BanChatMember.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.memberId == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.memberId.serialize(output);
			}
			output.writeInt(this.bannedUntilDate);
			output.writeBoolean(this.revokeMessages);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			BanChatMember banChatMember = (BanChatMember) o;
			if (this.chatId != banChatMember.chatId) {
				return false;
			}
			if (!Objects.equals(this.memberId, banChatMember.memberId)) {
				return false;
			}
			if (this.bannedUntilDate != banChatMember.bannedUntilDate) {
				return false;
			}
			if (this.revokeMessages != banChatMember.revokeMessages) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.memberId == null ? 0 : this.memberId.hashCode());
			return result;
		}
	}

	/**
	 * Blocks an original sender of a message in the Replies chat.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class BlockMessageSenderFromReplies extends Function<Ok> {


		/**
		 * The identifier of an incoming message in the Replies chat.
		**/
		public long messageId;

		/**
		 * Pass true to delete the message.
		**/
		public boolean deleteMessage;

		/**
		 * Pass true to delete all messages from the same sender.
		**/
		public boolean deleteAllMessages;

		/**
		 * Pass true to report the sender to the Telegram moderators.
		**/
		public boolean reportSpam;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1214384757;

		/**
		 * Blocks an original sender of a message in the Replies chat.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public BlockMessageSenderFromReplies() {}

		/**
		 * Blocks an original sender of a message in the Replies chat.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param messageId The identifier of an incoming message in the Replies chat.
		 * @param deleteMessage Pass true to delete the message.
		 * @param deleteAllMessages Pass true to delete all messages from the same sender.
		 * @param reportSpam Pass true to report the sender to the Telegram moderators.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public BlockMessageSenderFromReplies(long messageId,
				boolean deleteMessage,
				boolean deleteAllMessages,
				boolean reportSpam) {
			this.messageId = messageId;
			this.deleteMessage = deleteMessage;
			this.deleteAllMessages = deleteAllMessages;
			this.reportSpam = reportSpam;
		}

		/**
		 * Blocks an original sender of a message in the Replies chat.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public BlockMessageSenderFromReplies(DataInput input) throws IOException {
			this.messageId = input.readLong();
			this.deleteMessage = input.readBoolean();
			this.deleteAllMessages = input.readBoolean();
			this.reportSpam = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return BlockMessageSenderFromReplies.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(BlockMessageSenderFromReplies.CONSTRUCTOR);
			output.writeLong(this.messageId);
			output.writeBoolean(this.deleteMessage);
			output.writeBoolean(this.deleteAllMessages);
			output.writeBoolean(this.reportSpam);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			BlockMessageSenderFromReplies blockMessageSenderFromReplies = (BlockMessageSenderFromReplies) o;
			if (this.messageId != blockMessageSenderFromReplies.messageId) {
				return false;
			}
			if (this.deleteMessage != blockMessageSenderFromReplies.deleteMessage) {
				return false;
			}
			if (this.deleteAllMessages != blockMessageSenderFromReplies.deleteAllMessages) {
				return false;
			}
			if (this.reportSpam != blockMessageSenderFromReplies.reportSpam) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.messageId);
			return result;
		}
	}

	/**
	 * Checks whether Telegram Premium purchase is possible. Must be called
	 * before in-store Premium purchase.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class CanPurchasePremium extends Function<Ok> {


		/**
		 * Transaction purpose.
		**/
		public StorePaymentPurpose purpose;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -371319616;

		/**
		 * Checks whether Telegram Premium purchase is possible. Must be called before in-store Premium purchase.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public CanPurchasePremium() {}

		/**
		 * Checks whether Telegram Premium purchase is possible. Must be called before in-store Premium purchase.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param purpose Transaction purpose.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public CanPurchasePremium(StorePaymentPurpose purpose) {
			this.purpose = purpose;
		}

		/**
		 * Checks whether Telegram Premium purchase is possible. Must be called before in-store Premium purchase.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CanPurchasePremium(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case StorePaymentPurposePremiumSubscription.CONSTRUCTOR: this.purpose = new StorePaymentPurposePremiumSubscription(input); break;
					case StorePaymentPurposeGiftedPremium.CONSTRUCTOR: this.purpose = new StorePaymentPurposeGiftedPremium(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CanPurchasePremium.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CanPurchasePremium.CONSTRUCTOR);
			if (this.purpose == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.purpose.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CanPurchasePremium canPurchasePremium = (CanPurchasePremium) o;
			if (!Objects.equals(this.purpose, canPurchasePremium.purpose)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.purpose == null ? 0 : this.purpose.hashCode();
		}
	}

	/**
	 * Checks whether the current session can be used to transfer a chat
	 * ownership to another user.
	 * <p> Returns {@link CanTransferOwnershipResult
	 * CanTransferOwnershipResult} </p>
	**/
	public static final class CanTransferOwnership extends Function<CanTransferOwnershipResult> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 634602508;

		/**
		 * Checks whether the current session can be used to transfer a chat ownership to another user.
		 *
		 * <p> Returns {@link CanTransferOwnershipResult CanTransferOwnershipResult} </p>
		**/
		public CanTransferOwnership() {}

		/**
		 * Checks whether the current session can be used to transfer a chat ownership to another user.
		 *
		 * <p> Returns {@link CanTransferOwnershipResult CanTransferOwnershipResult} </p>
		 *
		 *
		 * <p> Returns {@link CanTransferOwnershipResult CanTransferOwnershipResult} </p>
		**/

		/**
		 * Checks whether the current session can be used to transfer a chat ownership to another user.
		 *
		 * <p> Returns {@link CanTransferOwnershipResult CanTransferOwnershipResult} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CanTransferOwnership(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CanTransferOwnership.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CanTransferOwnership.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return CanTransferOwnership.CONSTRUCTOR;
		}
	}

	/**
	 * Stops the downloading of a file. If a file has already been
	 * downloaded, does nothing.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class CancelDownloadFile extends Function<Ok> {


		/**
		 * Identifier of a file to stop downloading.
		**/
		public int fileId;

		/**
		 * Pass true to stop downloading only if it hasn&#039;t been started, i.e. request hasn&#039;t been sent to server.
		**/
		public boolean onlyIfPending;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1954524450;

		/**
		 * Stops the downloading of a file. If a file has already been downloaded, does nothing.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public CancelDownloadFile() {}

		/**
		 * Stops the downloading of a file. If a file has already been downloaded, does nothing.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param fileId Identifier of a file to stop downloading.
		 * @param onlyIfPending Pass true to stop downloading only if it hasn&#039;t been started, i.e. request hasn&#039;t been sent to server.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public CancelDownloadFile(int fileId, boolean onlyIfPending) {
			this.fileId = fileId;
			this.onlyIfPending = onlyIfPending;
		}

		/**
		 * Stops the downloading of a file. If a file has already been downloaded, does nothing.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CancelDownloadFile(DataInput input) throws IOException {
			this.fileId = input.readInt();
			this.onlyIfPending = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CancelDownloadFile.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CancelDownloadFile.CONSTRUCTOR);
			output.writeInt(this.fileId);
			output.writeBoolean(this.onlyIfPending);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CancelDownloadFile cancelDownloadFile = (CancelDownloadFile) o;
			if (this.fileId != cancelDownloadFile.fileId) {
				return false;
			}
			if (this.onlyIfPending != cancelDownloadFile.onlyIfPending) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.fileId);
			return result;
		}
	}

	/**
	 * Cancels reset of 2-step verification password. The method can be
	 * called if passwordState.pendingResetDate &gt; 0.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class CancelPasswordReset extends Function<Ok> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 940733538;

		/**
		 * Cancels reset of 2-step verification password. The method can be called if passwordState.pendingResetDate &gt; 0.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public CancelPasswordReset() {}

		/**
		 * Cancels reset of 2-step verification password. The method can be called if passwordState.pendingResetDate &gt; 0.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/

		/**
		 * Cancels reset of 2-step verification password. The method can be called if passwordState.pendingResetDate &gt; 0.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CancelPasswordReset(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CancelPasswordReset.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CancelPasswordReset.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return CancelPasswordReset.CONSTRUCTOR;
		}
	}

	/**
	 * Stops the preliminary uploading of a file. Supported only for files
	 * uploaded by using preliminaryUploadFile. For other files the behavior
	 * is undefined.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class CancelPreliminaryUploadFile extends Function<Ok> {


		/**
		 * Identifier of the file to stop uploading.
		**/
		public int fileId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 823412414;

		/**
		 * Stops the preliminary uploading of a file. Supported only for files uploaded by using preliminaryUploadFile. For other files the behavior is undefined.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public CancelPreliminaryUploadFile() {}

		/**
		 * Stops the preliminary uploading of a file. Supported only for files uploaded by using preliminaryUploadFile. For other files the behavior is undefined.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param fileId Identifier of the file to stop uploading.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public CancelPreliminaryUploadFile(int fileId) {
			this.fileId = fileId;
		}

		/**
		 * Stops the preliminary uploading of a file. Supported only for files uploaded by using preliminaryUploadFile. For other files the behavior is undefined.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CancelPreliminaryUploadFile(DataInput input) throws IOException {
			this.fileId = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CancelPreliminaryUploadFile.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CancelPreliminaryUploadFile.CONSTRUCTOR);
			output.writeInt(this.fileId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CancelPreliminaryUploadFile cancelPreliminaryUploadFile = (CancelPreliminaryUploadFile) o;
			if (this.fileId != cancelPreliminaryUploadFile.fileId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.fileId);
		}
	}

	/**
	 * Changes imported contacts using the list of contacts saved on the
	 * device. Imports newly added contacts and, if at least the file
	 * database is enabled, deletes recently deleted contacts. Query result
	 * depends on the result of the previous query, so only one query is
	 * possible at the same time.
	 * <p> Returns {@link ImportedContacts ImportedContacts} </p>
	**/
	public static final class ChangeImportedContacts extends Function<ImportedContacts> {


		/**
		 * The new list of contacts, contact&#039;s vCard are ignored and are not imported.
		**/
		public Contact[] contacts;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1968207955;

		/**
		 * Changes imported contacts using the list of contacts saved on the device. Imports newly added contacts and, if at least the file database is enabled, deletes recently deleted contacts. Query result depends on the result of the previous query, so only one query is possible at the same time.
		 *
		 * <p> Returns {@link ImportedContacts ImportedContacts} </p>
		**/
		public ChangeImportedContacts() {}

		/**
		 * Changes imported contacts using the list of contacts saved on the device. Imports newly added contacts and, if at least the file database is enabled, deletes recently deleted contacts. Query result depends on the result of the previous query, so only one query is possible at the same time.
		 *
		 * <p> Returns {@link ImportedContacts ImportedContacts} </p>
		 *
		 * @param contacts The new list of contacts, contact&#039;s vCard are ignored and are not imported.
		 *
		 * <p> Returns {@link ImportedContacts ImportedContacts} </p>
		**/
		public ChangeImportedContacts(Contact[] contacts) {
			this.contacts = contacts;
		}

		/**
		 * Changes imported contacts using the list of contacts saved on the device. Imports newly added contacts and, if at least the file database is enabled, deletes recently deleted contacts. Query result depends on the result of the previous query, so only one query is possible at the same time.
		 *
		 * <p> Returns {@link ImportedContacts ImportedContacts} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChangeImportedContacts(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.contacts = new Contact[input.readInt()];
				for (int i = 0; i < this.contacts.length; i++) {
					if (Contact.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.contacts[i] = new Contact(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChangeImportedContacts.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChangeImportedContacts.CONSTRUCTOR);
			if (this.contacts == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.contacts.length);
				for (int i = 0; i < this.contacts.length; i++) {
					this.contacts[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChangeImportedContacts changeImportedContacts = (ChangeImportedContacts) o;
			if (!Arrays.equals(this.contacts, changeImportedContacts.contacts)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.contacts);
		}
	}

	/**
	 * Changes the phone number of the user and sends an authentication code
	 * to the user&#039;s new phone number. On success, returns information
	 * about the sent code.
	 * <p> Returns {@link AuthenticationCodeInfo AuthenticationCodeInfo} </p>
	**/
	public static final class ChangePhoneNumber extends Function<AuthenticationCodeInfo> {


		/**
		 * The new phone number of the user in international format.
		**/
		public String phoneNumber;

		/**
		 * Settings for the authentication of the user&#039;s phone number; pass null to use default settings.
		**/
		public PhoneNumberAuthenticationSettings settings;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -124666973;

		/**
		 * Changes the phone number of the user and sends an authentication code to the user&#039;s new phone number. On success, returns information about the sent code.
		 *
		 * <p> Returns {@link AuthenticationCodeInfo AuthenticationCodeInfo} </p>
		**/
		public ChangePhoneNumber() {}

		/**
		 * Changes the phone number of the user and sends an authentication code to the user&#039;s new phone number. On success, returns information about the sent code.
		 *
		 * <p> Returns {@link AuthenticationCodeInfo AuthenticationCodeInfo} </p>
		 *
		 * @param phoneNumber The new phone number of the user in international format.
		 * @param settings Settings for the authentication of the user&#039;s phone number; pass null to use default settings.
		 *
		 * <p> Returns {@link AuthenticationCodeInfo AuthenticationCodeInfo} </p>
		**/
		public ChangePhoneNumber(String phoneNumber,
				PhoneNumberAuthenticationSettings settings) {
			this.phoneNumber = phoneNumber;
			this.settings = settings;
		}

		/**
		 * Changes the phone number of the user and sends an authentication code to the user&#039;s new phone number. On success, returns information about the sent code.
		 *
		 * <p> Returns {@link AuthenticationCodeInfo AuthenticationCodeInfo} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChangePhoneNumber(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] phoneNumberTmp = new byte[input.readInt()];
				input.readFully(phoneNumberTmp);
				this.phoneNumber = new String(phoneNumberTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (PhoneNumberAuthenticationSettings.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.settings = new PhoneNumberAuthenticationSettings(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChangePhoneNumber.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChangePhoneNumber.CONSTRUCTOR);
			if (this.phoneNumber == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] phoneNumberTmp = this.phoneNumber.getBytes(StandardCharsets.UTF_8);
				output.writeInt(phoneNumberTmp.length);
				output.write(phoneNumberTmp);
			}
			if (this.settings == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.settings.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChangePhoneNumber changePhoneNumber = (ChangePhoneNumber) o;
			if (this.phoneNumber != changePhoneNumber.phoneNumber) {
				return false;
			}
			if (!Objects.equals(this.settings, changePhoneNumber.settings)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.phoneNumber == null ? 0 : this.phoneNumber.hashCode();
			result = result * 31 + (this.settings == null ? 0 : this.settings.hashCode());
			return result;
		}
	}

	/**
	 * Installs/uninstalls or activates/archives a sticker set.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ChangeStickerSet extends Function<Ok> {


		/**
		 * Identifier of the sticker set.
		**/
		public long setId;

		/**
		 * The new value of isInstalled.
		**/
		public boolean isInstalled;

		/**
		 * The new value of isArchived. A sticker set can&#039;t be installed and archived simultaneously.
		**/
		public boolean isArchived;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 449357293;

		/**
		 * Installs/uninstalls or activates/archives a sticker set.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ChangeStickerSet() {}

		/**
		 * Installs/uninstalls or activates/archives a sticker set.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param setId Identifier of the sticker set.
		 * @param isInstalled The new value of isInstalled.
		 * @param isArchived The new value of isArchived. A sticker set can&#039;t be installed and archived simultaneously.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ChangeStickerSet(long setId, boolean isInstalled, boolean isArchived) {
			this.setId = setId;
			this.isInstalled = isInstalled;
			this.isArchived = isArchived;
		}

		/**
		 * Installs/uninstalls or activates/archives a sticker set.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ChangeStickerSet(DataInput input) throws IOException {
			this.setId = input.readLong();
			this.isInstalled = input.readBoolean();
			this.isArchived = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ChangeStickerSet.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ChangeStickerSet.CONSTRUCTOR);
			output.writeLong(this.setId);
			output.writeBoolean(this.isInstalled);
			output.writeBoolean(this.isArchived);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ChangeStickerSet changeStickerSet = (ChangeStickerSet) o;
			if (this.setId != changeStickerSet.setId) {
				return false;
			}
			if (this.isInstalled != changeStickerSet.isInstalled) {
				return false;
			}
			if (this.isArchived != changeStickerSet.isArchived) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.setId);
			return result;
		}
	}

	/**
	 * Checks the authentication token of a bot; to log in as a bot. Works
	 * only when the current authorization state is
	 * authorizationStateWaitPhoneNumber. Can be used instead of
	 * setAuthenticationPhoneNumber and checkAuthenticationCode to log in.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class CheckAuthenticationBotToken extends Function<Ok> {


		/**
		 * The bot token.
		**/
		public String token;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 639321206;

		/**
		 * Checks the authentication token of a bot; to log in as a bot. Works only when the current authorization state is authorizationStateWaitPhoneNumber. Can be used instead of setAuthenticationPhoneNumber and checkAuthenticationCode to log in.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public CheckAuthenticationBotToken() {}

		/**
		 * Checks the authentication token of a bot; to log in as a bot. Works only when the current authorization state is authorizationStateWaitPhoneNumber. Can be used instead of setAuthenticationPhoneNumber and checkAuthenticationCode to log in.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param token The bot token.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public CheckAuthenticationBotToken(String token) {
			this.token = token;
		}

		/**
		 * Checks the authentication token of a bot; to log in as a bot. Works only when the current authorization state is authorizationStateWaitPhoneNumber. Can be used instead of setAuthenticationPhoneNumber and checkAuthenticationCode to log in.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CheckAuthenticationBotToken(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] tokenTmp = new byte[input.readInt()];
				input.readFully(tokenTmp);
				this.token = new String(tokenTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CheckAuthenticationBotToken.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CheckAuthenticationBotToken.CONSTRUCTOR);
			if (this.token == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] tokenTmp = this.token.getBytes(StandardCharsets.UTF_8);
				output.writeInt(tokenTmp.length);
				output.write(tokenTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CheckAuthenticationBotToken checkAuthenticationBotToken = (CheckAuthenticationBotToken) o;
			if (this.token != checkAuthenticationBotToken.token) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.token == null ? 0 : this.token.hashCode();
		}
	}

	/**
	 * Checks the authentication code. Works only when the current
	 * authorization state is authorizationStateWaitCode.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class CheckAuthenticationCode extends Function<Ok> {


		/**
		 * Authentication code to check.
		**/
		public String code;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -302103382;

		/**
		 * Checks the authentication code. Works only when the current authorization state is authorizationStateWaitCode.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public CheckAuthenticationCode() {}

		/**
		 * Checks the authentication code. Works only when the current authorization state is authorizationStateWaitCode.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param code Authentication code to check.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public CheckAuthenticationCode(String code) {
			this.code = code;
		}

		/**
		 * Checks the authentication code. Works only when the current authorization state is authorizationStateWaitCode.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CheckAuthenticationCode(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] codeTmp = new byte[input.readInt()];
				input.readFully(codeTmp);
				this.code = new String(codeTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CheckAuthenticationCode.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CheckAuthenticationCode.CONSTRUCTOR);
			if (this.code == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] codeTmp = this.code.getBytes(StandardCharsets.UTF_8);
				output.writeInt(codeTmp.length);
				output.write(codeTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CheckAuthenticationCode checkAuthenticationCode = (CheckAuthenticationCode) o;
			if (this.code != checkAuthenticationCode.code) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.code == null ? 0 : this.code.hashCode();
		}
	}

	/**
	 * Checks the authentication of a email address. Works only when the
	 * current authorization state is authorizationStateWaitEmailCode.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class CheckAuthenticationEmailCode extends Function<Ok> {


		/**
		 * Email address authentication to check.
		**/
		public EmailAddressAuthentication code;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -582827361;

		/**
		 * Checks the authentication of a email address. Works only when the current authorization state is authorizationStateWaitEmailCode.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public CheckAuthenticationEmailCode() {}

		/**
		 * Checks the authentication of a email address. Works only when the current authorization state is authorizationStateWaitEmailCode.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param code Email address authentication to check.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public CheckAuthenticationEmailCode(EmailAddressAuthentication code) {
			this.code = code;
		}

		/**
		 * Checks the authentication of a email address. Works only when the current authorization state is authorizationStateWaitEmailCode.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CheckAuthenticationEmailCode(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case EmailAddressAuthenticationCode.CONSTRUCTOR: this.code = new EmailAddressAuthenticationCode(input); break;
					case EmailAddressAuthenticationAppleId.CONSTRUCTOR: this.code = new EmailAddressAuthenticationAppleId(input); break;
					case EmailAddressAuthenticationGoogleId.CONSTRUCTOR: this.code = new EmailAddressAuthenticationGoogleId(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CheckAuthenticationEmailCode.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CheckAuthenticationEmailCode.CONSTRUCTOR);
			if (this.code == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.code.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CheckAuthenticationEmailCode checkAuthenticationEmailCode = (CheckAuthenticationEmailCode) o;
			if (!Objects.equals(this.code, checkAuthenticationEmailCode.code)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.code == null ? 0 : this.code.hashCode();
		}
	}

	/**
	 * Checks the 2-step verification password for correctness. Works only
	 * when the current authorization state is
	 * authorizationStateWaitPassword.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class CheckAuthenticationPassword extends Function<Ok> {


		/**
		 * The 2-step verification password to check.
		**/
		public String password;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2025698400;

		/**
		 * Checks the 2-step verification password for correctness. Works only when the current authorization state is authorizationStateWaitPassword.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public CheckAuthenticationPassword() {}

		/**
		 * Checks the 2-step verification password for correctness. Works only when the current authorization state is authorizationStateWaitPassword.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param password The 2-step verification password to check.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public CheckAuthenticationPassword(String password) {
			this.password = password;
		}

		/**
		 * Checks the 2-step verification password for correctness. Works only when the current authorization state is authorizationStateWaitPassword.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CheckAuthenticationPassword(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] passwordTmp = new byte[input.readInt()];
				input.readFully(passwordTmp);
				this.password = new String(passwordTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CheckAuthenticationPassword.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CheckAuthenticationPassword.CONSTRUCTOR);
			if (this.password == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] passwordTmp = this.password.getBytes(StandardCharsets.UTF_8);
				output.writeInt(passwordTmp.length);
				output.write(passwordTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CheckAuthenticationPassword checkAuthenticationPassword = (CheckAuthenticationPassword) o;
			if (this.password != checkAuthenticationPassword.password) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.password == null ? 0 : this.password.hashCode();
		}
	}

	/**
	 * Checks whether a 2-step verification password recovery code sent to
	 * an email address is valid. Works only when the current authorization
	 * state is authorizationStateWaitPassword.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class CheckAuthenticationPasswordRecoveryCode extends Function<Ok> {


		/**
		 * Recovery code to check.
		**/
		public String recoveryCode;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -603309083;

		/**
		 * Checks whether a 2-step verification password recovery code sent to an email address is valid. Works only when the current authorization state is authorizationStateWaitPassword.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public CheckAuthenticationPasswordRecoveryCode() {}

		/**
		 * Checks whether a 2-step verification password recovery code sent to an email address is valid. Works only when the current authorization state is authorizationStateWaitPassword.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param recoveryCode Recovery code to check.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public CheckAuthenticationPasswordRecoveryCode(String recoveryCode) {
			this.recoveryCode = recoveryCode;
		}

		/**
		 * Checks whether a 2-step verification password recovery code sent to an email address is valid. Works only when the current authorization state is authorizationStateWaitPassword.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CheckAuthenticationPasswordRecoveryCode(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] recoveryCodeTmp = new byte[input.readInt()];
				input.readFully(recoveryCodeTmp);
				this.recoveryCode = new String(recoveryCodeTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CheckAuthenticationPasswordRecoveryCode.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CheckAuthenticationPasswordRecoveryCode.CONSTRUCTOR);
			if (this.recoveryCode == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] recoveryCodeTmp = this.recoveryCode.getBytes(StandardCharsets.UTF_8);
				output.writeInt(recoveryCodeTmp.length);
				output.write(recoveryCodeTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CheckAuthenticationPasswordRecoveryCode checkAuthenticationPasswordRecoveryCode = (CheckAuthenticationPasswordRecoveryCode) o;
			if (this.recoveryCode != checkAuthenticationPasswordRecoveryCode.recoveryCode) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.recoveryCode == null ? 0 : this.recoveryCode.hashCode();
		}
	}

	/**
	 * Checks the authentication code sent to confirm a new phone number of
	 * the user.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class CheckChangePhoneNumberCode extends Function<Ok> {


		/**
		 * Authentication code to check.
		**/
		public String code;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1720278429;

		/**
		 * Checks the authentication code sent to confirm a new phone number of the user.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public CheckChangePhoneNumberCode() {}

		/**
		 * Checks the authentication code sent to confirm a new phone number of the user.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param code Authentication code to check.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public CheckChangePhoneNumberCode(String code) {
			this.code = code;
		}

		/**
		 * Checks the authentication code sent to confirm a new phone number of the user.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CheckChangePhoneNumberCode(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] codeTmp = new byte[input.readInt()];
				input.readFully(codeTmp);
				this.code = new String(codeTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CheckChangePhoneNumberCode.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CheckChangePhoneNumberCode.CONSTRUCTOR);
			if (this.code == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] codeTmp = this.code.getBytes(StandardCharsets.UTF_8);
				output.writeInt(codeTmp.length);
				output.write(codeTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CheckChangePhoneNumberCode checkChangePhoneNumberCode = (CheckChangePhoneNumberCode) o;
			if (this.code != checkChangePhoneNumberCode.code) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.code == null ? 0 : this.code.hashCode();
		}
	}

	/**
	 * Checks the validity of an invite link for a chat folder and returns
	 * information about the corresponding chat folder.
	 * <p> Returns {@link ChatFolderInviteLinkInfo ChatFolderInviteLinkInfo}
	 * </p>
	**/
	public static final class CheckChatFolderInviteLink extends Function<ChatFolderInviteLinkInfo> {


		/**
		 * Invite link to be checked.
		**/
		public String inviteLink;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 522557851;

		/**
		 * Checks the validity of an invite link for a chat folder and returns information about the corresponding chat folder.
		 *
		 * <p> Returns {@link ChatFolderInviteLinkInfo ChatFolderInviteLinkInfo} </p>
		**/
		public CheckChatFolderInviteLink() {}

		/**
		 * Checks the validity of an invite link for a chat folder and returns information about the corresponding chat folder.
		 *
		 * <p> Returns {@link ChatFolderInviteLinkInfo ChatFolderInviteLinkInfo} </p>
		 *
		 * @param inviteLink Invite link to be checked.
		 *
		 * <p> Returns {@link ChatFolderInviteLinkInfo ChatFolderInviteLinkInfo} </p>
		**/
		public CheckChatFolderInviteLink(String inviteLink) {
			this.inviteLink = inviteLink;
		}

		/**
		 * Checks the validity of an invite link for a chat folder and returns information about the corresponding chat folder.
		 *
		 * <p> Returns {@link ChatFolderInviteLinkInfo ChatFolderInviteLinkInfo} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CheckChatFolderInviteLink(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] inviteLinkTmp = new byte[input.readInt()];
				input.readFully(inviteLinkTmp);
				this.inviteLink = new String(inviteLinkTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CheckChatFolderInviteLink.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CheckChatFolderInviteLink.CONSTRUCTOR);
			if (this.inviteLink == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] inviteLinkTmp = this.inviteLink.getBytes(StandardCharsets.UTF_8);
				output.writeInt(inviteLinkTmp.length);
				output.write(inviteLinkTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CheckChatFolderInviteLink checkChatFolderInviteLink = (CheckChatFolderInviteLink) o;
			if (this.inviteLink != checkChatFolderInviteLink.inviteLink) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.inviteLink == null ? 0 : this.inviteLink.hashCode();
		}
	}

	/**
	 * Checks the validity of an invite link for a chat and returns
	 * information about the corresponding chat.
	 * <p> Returns {@link ChatInviteLinkInfo ChatInviteLinkInfo} </p>
	**/
	public static final class CheckChatInviteLink extends Function<ChatInviteLinkInfo> {


		/**
		 * Invite link to be checked.
		**/
		public String inviteLink;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -496940997;

		/**
		 * Checks the validity of an invite link for a chat and returns information about the corresponding chat.
		 *
		 * <p> Returns {@link ChatInviteLinkInfo ChatInviteLinkInfo} </p>
		**/
		public CheckChatInviteLink() {}

		/**
		 * Checks the validity of an invite link for a chat and returns information about the corresponding chat.
		 *
		 * <p> Returns {@link ChatInviteLinkInfo ChatInviteLinkInfo} </p>
		 *
		 * @param inviteLink Invite link to be checked.
		 *
		 * <p> Returns {@link ChatInviteLinkInfo ChatInviteLinkInfo} </p>
		**/
		public CheckChatInviteLink(String inviteLink) {
			this.inviteLink = inviteLink;
		}

		/**
		 * Checks the validity of an invite link for a chat and returns information about the corresponding chat.
		 *
		 * <p> Returns {@link ChatInviteLinkInfo ChatInviteLinkInfo} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CheckChatInviteLink(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] inviteLinkTmp = new byte[input.readInt()];
				input.readFully(inviteLinkTmp);
				this.inviteLink = new String(inviteLinkTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CheckChatInviteLink.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CheckChatInviteLink.CONSTRUCTOR);
			if (this.inviteLink == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] inviteLinkTmp = this.inviteLink.getBytes(StandardCharsets.UTF_8);
				output.writeInt(inviteLinkTmp.length);
				output.write(inviteLinkTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CheckChatInviteLink checkChatInviteLink = (CheckChatInviteLink) o;
			if (this.inviteLink != checkChatInviteLink.inviteLink) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.inviteLink == null ? 0 : this.inviteLink.hashCode();
		}
	}

	/**
	 * Checks whether a username can be set for a chat.
	 * <p> Returns {@link CheckChatUsernameResult CheckChatUsernameResult}
	 * </p>
	**/
	public static final class CheckChatUsername extends Function<CheckChatUsernameResult> {


		/**
		 * Chat identifier; must be identifier of a supergroup chat, or a channel chat, or a private chat with self, or zero if the chat is being created.
		**/
		public long chatId;

		/**
		 * Username to be checked.
		**/
		public String username;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -119119344;

		/**
		 * Checks whether a username can be set for a chat.
		 *
		 * <p> Returns {@link CheckChatUsernameResult CheckChatUsernameResult} </p>
		**/
		public CheckChatUsername() {}

		/**
		 * Checks whether a username can be set for a chat.
		 *
		 * <p> Returns {@link CheckChatUsernameResult CheckChatUsernameResult} </p>
		 *
		 * @param chatId Chat identifier; must be identifier of a supergroup chat, or a channel chat, or a private chat with self, or zero if the chat is being created.
		 * @param username Username to be checked.
		 *
		 * <p> Returns {@link CheckChatUsernameResult CheckChatUsernameResult} </p>
		**/
		public CheckChatUsername(long chatId, String username) {
			this.chatId = chatId;
			this.username = username;
		}

		/**
		 * Checks whether a username can be set for a chat.
		 *
		 * <p> Returns {@link CheckChatUsernameResult CheckChatUsernameResult} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CheckChatUsername(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				byte[] usernameTmp = new byte[input.readInt()];
				input.readFully(usernameTmp);
				this.username = new String(usernameTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CheckChatUsername.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CheckChatUsername.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.username == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] usernameTmp = this.username.getBytes(StandardCharsets.UTF_8);
				output.writeInt(usernameTmp.length);
				output.write(usernameTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CheckChatUsername checkChatUsername = (CheckChatUsername) o;
			if (this.chatId != checkChatUsername.chatId) {
				return false;
			}
			if (this.username != checkChatUsername.username) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.username == null ? 0 : this.username.hashCode());
			return result;
		}
	}

	/**
	 * Checks whether the maximum number of owned public chats has been
	 * reached. Returns corresponding error if the limit was reached. The
	 * limit can be increased with Telegram Premium.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class CheckCreatedPublicChatsLimit extends Function<Ok> {


		/**
		 * Type of the public chats, for which to check the limit.
		**/
		public PublicChatType type;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -445546591;

		/**
		 * Checks whether the maximum number of owned public chats has been reached. Returns corresponding error if the limit was reached. The limit can be increased with Telegram Premium.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public CheckCreatedPublicChatsLimit() {}

		/**
		 * Checks whether the maximum number of owned public chats has been reached. Returns corresponding error if the limit was reached. The limit can be increased with Telegram Premium.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param type Type of the public chats, for which to check the limit.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public CheckCreatedPublicChatsLimit(PublicChatType type) {
			this.type = type;
		}

		/**
		 * Checks whether the maximum number of owned public chats has been reached. Returns corresponding error if the limit was reached. The limit can be increased with Telegram Premium.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CheckCreatedPublicChatsLimit(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case PublicChatTypeHasUsername.CONSTRUCTOR: this.type = new PublicChatTypeHasUsername(input); break;
					case PublicChatTypeIsLocationBased.CONSTRUCTOR: this.type = new PublicChatTypeIsLocationBased(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CheckCreatedPublicChatsLimit.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CheckCreatedPublicChatsLimit.CONSTRUCTOR);
			if (this.type == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.type.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CheckCreatedPublicChatsLimit checkCreatedPublicChatsLimit = (CheckCreatedPublicChatsLimit) o;
			if (!Objects.equals(this.type, checkCreatedPublicChatsLimit.type)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.type == null ? 0 : this.type.hashCode();
		}
	}

	/**
	 * Checks the email address verification code for Telegram Passport.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class CheckEmailAddressVerificationCode extends Function<Ok> {


		/**
		 * Verification code to check.
		**/
		public String code;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -426386685;

		/**
		 * Checks the email address verification code for Telegram Passport.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public CheckEmailAddressVerificationCode() {}

		/**
		 * Checks the email address verification code for Telegram Passport.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param code Verification code to check.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public CheckEmailAddressVerificationCode(String code) {
			this.code = code;
		}

		/**
		 * Checks the email address verification code for Telegram Passport.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CheckEmailAddressVerificationCode(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] codeTmp = new byte[input.readInt()];
				input.readFully(codeTmp);
				this.code = new String(codeTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CheckEmailAddressVerificationCode.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CheckEmailAddressVerificationCode.CONSTRUCTOR);
			if (this.code == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] codeTmp = this.code.getBytes(StandardCharsets.UTF_8);
				output.writeInt(codeTmp.length);
				output.write(codeTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CheckEmailAddressVerificationCode checkEmailAddressVerificationCode = (CheckEmailAddressVerificationCode) o;
			if (this.code != checkEmailAddressVerificationCode.code) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.code == null ? 0 : this.code.hashCode();
		}
	}

	/**
	 * Checks the login email address authentication.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class CheckLoginEmailAddressCode extends Function<Ok> {


		/**
		 * Email address authentication to check.
		**/
		public EmailAddressAuthentication code;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1454244766;

		/**
		 * Checks the login email address authentication.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public CheckLoginEmailAddressCode() {}

		/**
		 * Checks the login email address authentication.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param code Email address authentication to check.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public CheckLoginEmailAddressCode(EmailAddressAuthentication code) {
			this.code = code;
		}

		/**
		 * Checks the login email address authentication.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CheckLoginEmailAddressCode(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case EmailAddressAuthenticationCode.CONSTRUCTOR: this.code = new EmailAddressAuthenticationCode(input); break;
					case EmailAddressAuthenticationAppleId.CONSTRUCTOR: this.code = new EmailAddressAuthenticationAppleId(input); break;
					case EmailAddressAuthenticationGoogleId.CONSTRUCTOR: this.code = new EmailAddressAuthenticationGoogleId(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CheckLoginEmailAddressCode.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CheckLoginEmailAddressCode.CONSTRUCTOR);
			if (this.code == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.code.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CheckLoginEmailAddressCode checkLoginEmailAddressCode = (CheckLoginEmailAddressCode) o;
			if (!Objects.equals(this.code, checkLoginEmailAddressCode.code)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.code == null ? 0 : this.code.hashCode();
		}
	}

	/**
	 * Checks whether a 2-step verification password recovery code sent to
	 * an email address is valid.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class CheckPasswordRecoveryCode extends Function<Ok> {


		/**
		 * Recovery code to check.
		**/
		public String recoveryCode;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -200794600;

		/**
		 * Checks whether a 2-step verification password recovery code sent to an email address is valid.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public CheckPasswordRecoveryCode() {}

		/**
		 * Checks whether a 2-step verification password recovery code sent to an email address is valid.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param recoveryCode Recovery code to check.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public CheckPasswordRecoveryCode(String recoveryCode) {
			this.recoveryCode = recoveryCode;
		}

		/**
		 * Checks whether a 2-step verification password recovery code sent to an email address is valid.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CheckPasswordRecoveryCode(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] recoveryCodeTmp = new byte[input.readInt()];
				input.readFully(recoveryCodeTmp);
				this.recoveryCode = new String(recoveryCodeTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CheckPasswordRecoveryCode.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CheckPasswordRecoveryCode.CONSTRUCTOR);
			if (this.recoveryCode == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] recoveryCodeTmp = this.recoveryCode.getBytes(StandardCharsets.UTF_8);
				output.writeInt(recoveryCodeTmp.length);
				output.write(recoveryCodeTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CheckPasswordRecoveryCode checkPasswordRecoveryCode = (CheckPasswordRecoveryCode) o;
			if (this.recoveryCode != checkPasswordRecoveryCode.recoveryCode) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.recoveryCode == null ? 0 : this.recoveryCode.hashCode();
		}
	}

	/**
	 * Checks phone number confirmation code.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class CheckPhoneNumberConfirmationCode extends Function<Ok> {


		/**
		 * Confirmation code to check.
		**/
		public String code;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1348060966;

		/**
		 * Checks phone number confirmation code.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public CheckPhoneNumberConfirmationCode() {}

		/**
		 * Checks phone number confirmation code.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param code Confirmation code to check.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public CheckPhoneNumberConfirmationCode(String code) {
			this.code = code;
		}

		/**
		 * Checks phone number confirmation code.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CheckPhoneNumberConfirmationCode(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] codeTmp = new byte[input.readInt()];
				input.readFully(codeTmp);
				this.code = new String(codeTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CheckPhoneNumberConfirmationCode.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CheckPhoneNumberConfirmationCode.CONSTRUCTOR);
			if (this.code == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] codeTmp = this.code.getBytes(StandardCharsets.UTF_8);
				output.writeInt(codeTmp.length);
				output.write(codeTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CheckPhoneNumberConfirmationCode checkPhoneNumberConfirmationCode = (CheckPhoneNumberConfirmationCode) o;
			if (this.code != checkPhoneNumberConfirmationCode.code) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.code == null ? 0 : this.code.hashCode();
		}
	}

	/**
	 * Checks the phone number verification code for Telegram Passport.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class CheckPhoneNumberVerificationCode extends Function<Ok> {


		/**
		 * Verification code to check.
		**/
		public String code;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1497462718;

		/**
		 * Checks the phone number verification code for Telegram Passport.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public CheckPhoneNumberVerificationCode() {}

		/**
		 * Checks the phone number verification code for Telegram Passport.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param code Verification code to check.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public CheckPhoneNumberVerificationCode(String code) {
			this.code = code;
		}

		/**
		 * Checks the phone number verification code for Telegram Passport.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CheckPhoneNumberVerificationCode(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] codeTmp = new byte[input.readInt()];
				input.readFully(codeTmp);
				this.code = new String(codeTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CheckPhoneNumberVerificationCode.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CheckPhoneNumberVerificationCode.CONSTRUCTOR);
			if (this.code == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] codeTmp = this.code.getBytes(StandardCharsets.UTF_8);
				output.writeInt(codeTmp.length);
				output.write(codeTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CheckPhoneNumberVerificationCode checkPhoneNumberVerificationCode = (CheckPhoneNumberVerificationCode) o;
			if (this.code != checkPhoneNumberVerificationCode.code) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.code == null ? 0 : this.code.hashCode();
		}
	}

	/**
	 * Checks the 2-step verification recovery email address verification
	 * code.
	 * <p> Returns {@link PasswordState PasswordState} </p>
	**/
	public static final class CheckRecoveryEmailAddressCode extends Function<PasswordState> {


		/**
		 * Verification code to check.
		**/
		public String code;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1997039589;

		/**
		 * Checks the 2-step verification recovery email address verification code.
		 *
		 * <p> Returns {@link PasswordState PasswordState} </p>
		**/
		public CheckRecoveryEmailAddressCode() {}

		/**
		 * Checks the 2-step verification recovery email address verification code.
		 *
		 * <p> Returns {@link PasswordState PasswordState} </p>
		 *
		 * @param code Verification code to check.
		 *
		 * <p> Returns {@link PasswordState PasswordState} </p>
		**/
		public CheckRecoveryEmailAddressCode(String code) {
			this.code = code;
		}

		/**
		 * Checks the 2-step verification recovery email address verification code.
		 *
		 * <p> Returns {@link PasswordState PasswordState} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CheckRecoveryEmailAddressCode(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] codeTmp = new byte[input.readInt()];
				input.readFully(codeTmp);
				this.code = new String(codeTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CheckRecoveryEmailAddressCode.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CheckRecoveryEmailAddressCode.CONSTRUCTOR);
			if (this.code == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] codeTmp = this.code.getBytes(StandardCharsets.UTF_8);
				output.writeInt(codeTmp.length);
				output.write(codeTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CheckRecoveryEmailAddressCode checkRecoveryEmailAddressCode = (CheckRecoveryEmailAddressCode) o;
			if (this.code != checkRecoveryEmailAddressCode.code) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.code == null ? 0 : this.code.hashCode();
		}
	}

	/**
	 * Checks whether a name can be used for a new sticker set.
	 * <p> Returns {@link CheckStickerSetNameResult
	 * CheckStickerSetNameResult} </p>
	**/
	public static final class CheckStickerSetName extends Function<CheckStickerSetNameResult> {


		/**
		 * Name to be checked.
		**/
		public String name;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1789392642;

		/**
		 * Checks whether a name can be used for a new sticker set.
		 *
		 * <p> Returns {@link CheckStickerSetNameResult CheckStickerSetNameResult} </p>
		**/
		public CheckStickerSetName() {}

		/**
		 * Checks whether a name can be used for a new sticker set.
		 *
		 * <p> Returns {@link CheckStickerSetNameResult CheckStickerSetNameResult} </p>
		 *
		 * @param name Name to be checked.
		 *
		 * <p> Returns {@link CheckStickerSetNameResult CheckStickerSetNameResult} </p>
		**/
		public CheckStickerSetName(String name) {
			this.name = name;
		}

		/**
		 * Checks whether a name can be used for a new sticker set.
		 *
		 * <p> Returns {@link CheckStickerSetNameResult CheckStickerSetNameResult} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CheckStickerSetName(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] nameTmp = new byte[input.readInt()];
				input.readFully(nameTmp);
				this.name = new String(nameTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CheckStickerSetName.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CheckStickerSetName.CONSTRUCTOR);
			if (this.name == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nameTmp = this.name.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nameTmp.length);
				output.write(nameTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CheckStickerSetName checkStickerSetName = (CheckStickerSetName) o;
			if (this.name != checkStickerSetName.name) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.name == null ? 0 : this.name.hashCode();
		}
	}

	/**
	 * Removes potentially dangerous characters from the name of a file. The
	 * encoding of the file name is supposed to be UTF-8. Returns an empty
	 * string on failure. Can be called synchronously.
	 * <p> Returns {@link Text Text} </p>
	**/
	public static final class CleanFileName extends Function<Text> {


		/**
		 * File name or path to the file.
		**/
		public String fileName;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 967964667;

		/**
		 * Removes potentially dangerous characters from the name of a file. The encoding of the file name is supposed to be UTF-8. Returns an empty string on failure. Can be called synchronously.
		 *
		 * <p> Returns {@link Text Text} </p>
		**/
		public CleanFileName() {}

		/**
		 * Removes potentially dangerous characters from the name of a file. The encoding of the file name is supposed to be UTF-8. Returns an empty string on failure. Can be called synchronously.
		 *
		 * <p> Returns {@link Text Text} </p>
		 *
		 * @param fileName File name or path to the file.
		 *
		 * <p> Returns {@link Text Text} </p>
		**/
		public CleanFileName(String fileName) {
			this.fileName = fileName;
		}

		/**
		 * Removes potentially dangerous characters from the name of a file. The encoding of the file name is supposed to be UTF-8. Returns an empty string on failure. Can be called synchronously.
		 *
		 * <p> Returns {@link Text Text} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CleanFileName(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] fileNameTmp = new byte[input.readInt()];
				input.readFully(fileNameTmp);
				this.fileName = new String(fileNameTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CleanFileName.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CleanFileName.CONSTRUCTOR);
			if (this.fileName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] fileNameTmp = this.fileName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(fileNameTmp.length);
				output.write(fileNameTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CleanFileName cleanFileName = (CleanFileName) o;
			if (this.fileName != cleanFileName.fileName) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.fileName == null ? 0 : this.fileName.hashCode();
		}
	}

	/**
	 * Clears message drafts in all chats.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ClearAllDraftMessages extends Function<Ok> {


		/**
		 * Pass true to keep local message drafts in secret chats.
		**/
		public boolean excludeSecretChats;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -46369573;

		/**
		 * Clears message drafts in all chats.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ClearAllDraftMessages() {}

		/**
		 * Clears message drafts in all chats.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param excludeSecretChats Pass true to keep local message drafts in secret chats.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ClearAllDraftMessages(boolean excludeSecretChats) {
			this.excludeSecretChats = excludeSecretChats;
		}

		/**
		 * Clears message drafts in all chats.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ClearAllDraftMessages(DataInput input) throws IOException {
			this.excludeSecretChats = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ClearAllDraftMessages.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ClearAllDraftMessages.CONSTRUCTOR);
			output.writeBoolean(this.excludeSecretChats);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ClearAllDraftMessages clearAllDraftMessages = (ClearAllDraftMessages) o;
			if (this.excludeSecretChats != clearAllDraftMessages.excludeSecretChats) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Boolean.hashCode(this.excludeSecretChats);
		}
	}

	/**
	 * Clears the list of all autosave settings exceptions. The method is
	 * guaranteed to work only after at least one call to
	 * getAutosaveSettings.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ClearAutosaveSettingsExceptions extends Function<Ok> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1475109874;

		/**
		 * Clears the list of all autosave settings exceptions. The method is guaranteed to work only after at least one call to getAutosaveSettings.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ClearAutosaveSettingsExceptions() {}

		/**
		 * Clears the list of all autosave settings exceptions. The method is guaranteed to work only after at least one call to getAutosaveSettings.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/

		/**
		 * Clears the list of all autosave settings exceptions. The method is guaranteed to work only after at least one call to getAutosaveSettings.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ClearAutosaveSettingsExceptions(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ClearAutosaveSettingsExceptions.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ClearAutosaveSettingsExceptions.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ClearAutosaveSettingsExceptions.CONSTRUCTOR;
		}
	}

	/**
	 * Clears all imported contacts, contact list remains unchanged.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ClearImportedContacts extends Function<Ok> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 869503298;

		/**
		 * Clears all imported contacts, contact list remains unchanged.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ClearImportedContacts() {}

		/**
		 * Clears all imported contacts, contact list remains unchanged.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/

		/**
		 * Clears all imported contacts, contact list remains unchanged.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ClearImportedContacts(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ClearImportedContacts.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ClearImportedContacts.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ClearImportedContacts.CONSTRUCTOR;
		}
	}

	/**
	 * Clears the list of recently used emoji statuses.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ClearRecentEmojiStatuses extends Function<Ok> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -428749986;

		/**
		 * Clears the list of recently used emoji statuses.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ClearRecentEmojiStatuses() {}

		/**
		 * Clears the list of recently used emoji statuses.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/

		/**
		 * Clears the list of recently used emoji statuses.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ClearRecentEmojiStatuses(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ClearRecentEmojiStatuses.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ClearRecentEmojiStatuses.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ClearRecentEmojiStatuses.CONSTRUCTOR;
		}
	}

	/**
	 * Clears the list of recently used reactions.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ClearRecentReactions extends Function<Ok> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1298253650;

		/**
		 * Clears the list of recently used reactions.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ClearRecentReactions() {}

		/**
		 * Clears the list of recently used reactions.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/

		/**
		 * Clears the list of recently used reactions.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ClearRecentReactions(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ClearRecentReactions.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ClearRecentReactions.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ClearRecentReactions.CONSTRUCTOR;
		}
	}

	/**
	 * Clears the list of recently used stickers.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ClearRecentStickers extends Function<Ok> {


		/**
		 * Pass true to clear the list of stickers recently attached to photo or video files; pass false to clear the list of recently sent stickers.
		**/
		public boolean isAttached;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -321242684;

		/**
		 * Clears the list of recently used stickers.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ClearRecentStickers() {}

		/**
		 * Clears the list of recently used stickers.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param isAttached Pass true to clear the list of stickers recently attached to photo or video files; pass false to clear the list of recently sent stickers.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ClearRecentStickers(boolean isAttached) {
			this.isAttached = isAttached;
		}

		/**
		 * Clears the list of recently used stickers.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ClearRecentStickers(DataInput input) throws IOException {
			this.isAttached = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ClearRecentStickers.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ClearRecentStickers.CONSTRUCTOR);
			output.writeBoolean(this.isAttached);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ClearRecentStickers clearRecentStickers = (ClearRecentStickers) o;
			if (this.isAttached != clearRecentStickers.isAttached) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Boolean.hashCode(this.isAttached);
		}
	}

	/**
	 * Clears the list of recently found chats.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ClearRecentlyFoundChats extends Function<Ok> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -285582542;

		/**
		 * Clears the list of recently found chats.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ClearRecentlyFoundChats() {}

		/**
		 * Clears the list of recently found chats.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/

		/**
		 * Clears the list of recently found chats.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ClearRecentlyFoundChats(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ClearRecentlyFoundChats.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ClearRecentlyFoundChats.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ClearRecentlyFoundChats.CONSTRUCTOR;
		}
	}

	/**
	 * Informs TDLib that a message with an animated emoji was clicked by
	 * the user. Returns a big animated sticker to be played or a 404 error
	 * if usual animation needs to be played.
	 * <p> Returns {@link Sticker Sticker} </p>
	**/
	public static final class ClickAnimatedEmojiMessage extends Function<Sticker> {


		/**
		 * Chat identifier of the message.
		**/
		public long chatId;

		/**
		 * Identifier of the clicked message.
		**/
		public long messageId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 196179554;

		/**
		 * Informs TDLib that a message with an animated emoji was clicked by the user. Returns a big animated sticker to be played or a 404 error if usual animation needs to be played.
		 *
		 * <p> Returns {@link Sticker Sticker} </p>
		**/
		public ClickAnimatedEmojiMessage() {}

		/**
		 * Informs TDLib that a message with an animated emoji was clicked by the user. Returns a big animated sticker to be played or a 404 error if usual animation needs to be played.
		 *
		 * <p> Returns {@link Sticker Sticker} </p>
		 *
		 * @param chatId Chat identifier of the message.
		 * @param messageId Identifier of the clicked message.
		 *
		 * <p> Returns {@link Sticker Sticker} </p>
		**/
		public ClickAnimatedEmojiMessage(long chatId, long messageId) {
			this.chatId = chatId;
			this.messageId = messageId;
		}

		/**
		 * Informs TDLib that a message with an animated emoji was clicked by the user. Returns a big animated sticker to be played or a 404 error if usual animation needs to be played.
		 *
		 * <p> Returns {@link Sticker Sticker} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ClickAnimatedEmojiMessage(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ClickAnimatedEmojiMessage.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ClickAnimatedEmojiMessage.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ClickAnimatedEmojiMessage clickAnimatedEmojiMessage = (ClickAnimatedEmojiMessage) o;
			if (this.chatId != clickAnimatedEmojiMessage.chatId) {
				return false;
			}
			if (this.messageId != clickAnimatedEmojiMessage.messageId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Informs TDLib that the user clicked Premium subscription button on
	 * the Premium features screen.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ClickPremiumSubscriptionButton extends Function<Ok> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -369319162;

		/**
		 * Informs TDLib that the user clicked Premium subscription button on the Premium features screen.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ClickPremiumSubscriptionButton() {}

		/**
		 * Informs TDLib that the user clicked Premium subscription button on the Premium features screen.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/

		/**
		 * Informs TDLib that the user clicked Premium subscription button on the Premium features screen.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ClickPremiumSubscriptionButton(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ClickPremiumSubscriptionButton.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ClickPremiumSubscriptionButton.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ClickPremiumSubscriptionButton.CONSTRUCTOR;
		}
	}

	/**
	 * Closes the TDLib instance. All databases will be flushed to disk and
	 * properly closed. After the close completes, updateAuthorizationState
	 * with authorizationStateClosed will be sent. Can be called before
	 * initialization.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class Close extends Function<Ok> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1187782273;

		/**
		 * Closes the TDLib instance. All databases will be flushed to disk and properly closed. After the close completes, updateAuthorizationState with authorizationStateClosed will be sent. Can be called before initialization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public Close() {}

		/**
		 * Closes the TDLib instance. All databases will be flushed to disk and properly closed. After the close completes, updateAuthorizationState with authorizationStateClosed will be sent. Can be called before initialization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/

		/**
		 * Closes the TDLib instance. All databases will be flushed to disk and properly closed. After the close completes, updateAuthorizationState with authorizationStateClosed will be sent. Can be called before initialization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public Close(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return Close.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(Close.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Close.CONSTRUCTOR;
		}
	}

	/**
	 * Informs TDLib that the chat is closed by the user. Many useful
	 * activities depend on the chat being opened or closed.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class CloseChat extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 39749353;

		/**
		 * Informs TDLib that the chat is closed by the user. Many useful activities depend on the chat being opened or closed.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public CloseChat() {}

		/**
		 * Informs TDLib that the chat is closed by the user. Many useful activities depend on the chat being opened or closed.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public CloseChat(long chatId) {
			this.chatId = chatId;
		}

		/**
		 * Informs TDLib that the chat is closed by the user. Many useful activities depend on the chat being opened or closed.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CloseChat(DataInput input) throws IOException {
			this.chatId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CloseChat.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CloseChat.CONSTRUCTOR);
			output.writeLong(this.chatId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CloseChat closeChat = (CloseChat) o;
			if (this.chatId != closeChat.chatId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.chatId);
		}
	}

	/**
	 * Closes a secret chat, effectively transferring its state to
	 * secretChatStateClosed.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class CloseSecretChat extends Function<Ok> {


		/**
		 * Secret chat identifier.
		**/
		public int secretChatId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -471006133;

		/**
		 * Closes a secret chat, effectively transferring its state to secretChatStateClosed.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public CloseSecretChat() {}

		/**
		 * Closes a secret chat, effectively transferring its state to secretChatStateClosed.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param secretChatId Secret chat identifier.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public CloseSecretChat(int secretChatId) {
			this.secretChatId = secretChatId;
		}

		/**
		 * Closes a secret chat, effectively transferring its state to secretChatStateClosed.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CloseSecretChat(DataInput input) throws IOException {
			this.secretChatId = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CloseSecretChat.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CloseSecretChat.CONSTRUCTOR);
			output.writeInt(this.secretChatId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CloseSecretChat closeSecretChat = (CloseSecretChat) o;
			if (this.secretChatId != closeSecretChat.secretChatId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.secretChatId);
		}
	}

	/**
	 * Informs TDLib that a previously opened Web App was closed.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class CloseWebApp extends Function<Ok> {


		/**
		 * Identifier of Web App launch, received from openWebApp.
		**/
		public long webAppLaunchId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1755391174;

		/**
		 * Informs TDLib that a previously opened Web App was closed.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public CloseWebApp() {}

		/**
		 * Informs TDLib that a previously opened Web App was closed.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param webAppLaunchId Identifier of Web App launch, received from openWebApp.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public CloseWebApp(long webAppLaunchId) {
			this.webAppLaunchId = webAppLaunchId;
		}

		/**
		 * Informs TDLib that a previously opened Web App was closed.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CloseWebApp(DataInput input) throws IOException {
			this.webAppLaunchId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CloseWebApp.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CloseWebApp.CONSTRUCTOR);
			output.writeLong(this.webAppLaunchId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CloseWebApp closeWebApp = (CloseWebApp) o;
			if (this.webAppLaunchId != closeWebApp.webAppLaunchId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.webAppLaunchId);
		}
	}

	/**
	 * Confirms QR code authentication on another device. Returns created
	 * session on success.
	 * <p> Returns {@link Session Session} </p>
	**/
	public static final class ConfirmQrCodeAuthentication extends Function<Session> {


		/**
		 * A link from a QR code. The link must be scanned by the in-app camera.
		**/
		public String link;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -376199379;

		/**
		 * Confirms QR code authentication on another device. Returns created session on success.
		 *
		 * <p> Returns {@link Session Session} </p>
		**/
		public ConfirmQrCodeAuthentication() {}

		/**
		 * Confirms QR code authentication on another device. Returns created session on success.
		 *
		 * <p> Returns {@link Session Session} </p>
		 *
		 * @param link A link from a QR code. The link must be scanned by the in-app camera.
		 *
		 * <p> Returns {@link Session Session} </p>
		**/
		public ConfirmQrCodeAuthentication(String link) {
			this.link = link;
		}

		/**
		 * Confirms QR code authentication on another device. Returns created session on success.
		 *
		 * <p> Returns {@link Session Session} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ConfirmQrCodeAuthentication(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] linkTmp = new byte[input.readInt()];
				input.readFully(linkTmp);
				this.link = new String(linkTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ConfirmQrCodeAuthentication.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ConfirmQrCodeAuthentication.CONSTRUCTOR);
			if (this.link == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] linkTmp = this.link.getBytes(StandardCharsets.UTF_8);
				output.writeInt(linkTmp.length);
				output.write(linkTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ConfirmQrCodeAuthentication confirmQrCodeAuthentication = (ConfirmQrCodeAuthentication) o;
			if (this.link != confirmQrCodeAuthentication.link) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.link == null ? 0 : this.link.hashCode();
		}
	}

	/**
	 * Returns an existing chat corresponding to a known basic group.
	 * <p> Returns {@link Chat Chat} </p>
	**/
	public static final class CreateBasicGroupChat extends Function<Chat> {


		/**
		 * Basic group identifier.
		**/
		public long basicGroupId;

		/**
		 * Pass true to create the chat without a network request. In this case all information about the chat except its type, title and photo can be incorrect.
		**/
		public boolean force;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1972024548;

		/**
		 * Returns an existing chat corresponding to a known basic group.
		 *
		 * <p> Returns {@link Chat Chat} </p>
		**/
		public CreateBasicGroupChat() {}

		/**
		 * Returns an existing chat corresponding to a known basic group.
		 *
		 * <p> Returns {@link Chat Chat} </p>
		 *
		 * @param basicGroupId Basic group identifier.
		 * @param force Pass true to create the chat without a network request. In this case all information about the chat except its type, title and photo can be incorrect.
		 *
		 * <p> Returns {@link Chat Chat} </p>
		**/
		public CreateBasicGroupChat(long basicGroupId, boolean force) {
			this.basicGroupId = basicGroupId;
			this.force = force;
		}

		/**
		 * Returns an existing chat corresponding to a known basic group.
		 *
		 * <p> Returns {@link Chat Chat} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CreateBasicGroupChat(DataInput input) throws IOException {
			this.basicGroupId = input.readLong();
			this.force = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CreateBasicGroupChat.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CreateBasicGroupChat.CONSTRUCTOR);
			output.writeLong(this.basicGroupId);
			output.writeBoolean(this.force);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CreateBasicGroupChat createBasicGroupChat = (CreateBasicGroupChat) o;
			if (this.basicGroupId != createBasicGroupChat.basicGroupId) {
				return false;
			}
			if (this.force != createBasicGroupChat.force) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.basicGroupId);
			return result;
		}
	}

	/**
	 * Creates a new call.
	 * <p> Returns {@link CallId CallId} </p>
	**/
	public static final class CreateCall extends Function<CallId> {


		/**
		 * Identifier of the user to be called.
		**/
		public long userId;

		/**
		 * The call protocols supported by the application.
		**/
		public CallProtocol protocol;

		/**
		 * Pass true to create a video call.
		**/
		public boolean isVideo;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1104663024;

		/**
		 * Creates a new call.
		 *
		 * <p> Returns {@link CallId CallId} </p>
		**/
		public CreateCall() {}

		/**
		 * Creates a new call.
		 *
		 * <p> Returns {@link CallId CallId} </p>
		 *
		 * @param userId Identifier of the user to be called.
		 * @param protocol The call protocols supported by the application.
		 * @param isVideo Pass true to create a video call.
		 *
		 * <p> Returns {@link CallId CallId} </p>
		**/
		public CreateCall(long userId, CallProtocol protocol, boolean isVideo) {
			this.userId = userId;
			this.protocol = protocol;
			this.isVideo = isVideo;
		}

		/**
		 * Creates a new call.
		 *
		 * <p> Returns {@link CallId CallId} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CreateCall(DataInput input) throws IOException {
			this.userId = input.readLong();
			if (input.readBoolean()) {
				if (CallProtocol.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.protocol = new CallProtocol(input);
			}
			this.isVideo = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CreateCall.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CreateCall.CONSTRUCTOR);
			output.writeLong(this.userId);
			if (this.protocol == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.protocol.serialize(output);
			}
			output.writeBoolean(this.isVideo);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CreateCall createCall = (CreateCall) o;
			if (this.userId != createCall.userId) {
				return false;
			}
			if (!Objects.equals(this.protocol, createCall.protocol)) {
				return false;
			}
			if (this.isVideo != createCall.isVideo) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.userId);
			result = result * 31 + (this.protocol == null ? 0 : this.protocol.hashCode());
			return result;
		}
	}

	/**
	 * Creates new chat folder. Returns information about the created chat
	 * folder. There can be up to
	 * getOption(&quot;chat_folder_count_max&quot;) chat folders, but the
	 * limit can be increased with Telegram Premium.
	 * <p> Returns {@link ChatFolderInfo ChatFolderInfo} </p>
	**/
	public static final class CreateChatFolder extends Function<ChatFolderInfo> {


		/**
		 * The new chat folder.
		**/
		public ChatFolder folder;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1015399680;

		/**
		 * Creates new chat folder. Returns information about the created chat folder. There can be up to getOption(&quot;chat_folder_count_max&quot;) chat folders, but the limit can be increased with Telegram Premium.
		 *
		 * <p> Returns {@link ChatFolderInfo ChatFolderInfo} </p>
		**/
		public CreateChatFolder() {}

		/**
		 * Creates new chat folder. Returns information about the created chat folder. There can be up to getOption(&quot;chat_folder_count_max&quot;) chat folders, but the limit can be increased with Telegram Premium.
		 *
		 * <p> Returns {@link ChatFolderInfo ChatFolderInfo} </p>
		 *
		 * @param folder The new chat folder.
		 *
		 * <p> Returns {@link ChatFolderInfo ChatFolderInfo} </p>
		**/
		public CreateChatFolder(ChatFolder folder) {
			this.folder = folder;
		}

		/**
		 * Creates new chat folder. Returns information about the created chat folder. There can be up to getOption(&quot;chat_folder_count_max&quot;) chat folders, but the limit can be increased with Telegram Premium.
		 *
		 * <p> Returns {@link ChatFolderInfo ChatFolderInfo} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CreateChatFolder(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (ChatFolder.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.folder = new ChatFolder(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CreateChatFolder.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CreateChatFolder.CONSTRUCTOR);
			if (this.folder == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.folder.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CreateChatFolder createChatFolder = (CreateChatFolder) o;
			if (!Objects.equals(this.folder, createChatFolder.folder)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.folder == null ? 0 : this.folder.hashCode();
		}
	}

	/**
	 * Creates a new invite link for a chat folder. A link can be created
	 * for a chat folder if it has only pinned and included chats.
	 * <p> Returns {@link ChatFolderInviteLink ChatFolderInviteLink} </p>
	**/
	public static final class CreateChatFolderInviteLink extends Function<ChatFolderInviteLink> {


		/**
		 * Chat folder identifier.
		**/
		public int chatFolderId;

		/**
		 * Name of the link; 0-32 characters.
		**/
		public String name;

		/**
		 * Identifiers of chats to be accessible by the invite link. Use getChatsForChatFolderInviteLink to get suitable chats. Basic groups will be automatically converted to supergroups before link creation.
		**/
		public long[] chatIds;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2037911099;

		/**
		 * Creates a new invite link for a chat folder. A link can be created for a chat folder if it has only pinned and included chats.
		 *
		 * <p> Returns {@link ChatFolderInviteLink ChatFolderInviteLink} </p>
		**/
		public CreateChatFolderInviteLink() {}

		/**
		 * Creates a new invite link for a chat folder. A link can be created for a chat folder if it has only pinned and included chats.
		 *
		 * <p> Returns {@link ChatFolderInviteLink ChatFolderInviteLink} </p>
		 *
		 * @param chatFolderId Chat folder identifier.
		 * @param name Name of the link; 0-32 characters.
		 * @param chatIds Identifiers of chats to be accessible by the invite link. Use getChatsForChatFolderInviteLink to get suitable chats. Basic groups will be automatically converted to supergroups before link creation.
		 *
		 * <p> Returns {@link ChatFolderInviteLink ChatFolderInviteLink} </p>
		**/
		public CreateChatFolderInviteLink(int chatFolderId, String name, long[] chatIds) {
			this.chatFolderId = chatFolderId;
			this.name = name;
			this.chatIds = chatIds;
		}

		/**
		 * Creates a new invite link for a chat folder. A link can be created for a chat folder if it has only pinned and included chats.
		 *
		 * <p> Returns {@link ChatFolderInviteLink ChatFolderInviteLink} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CreateChatFolderInviteLink(DataInput input) throws IOException {
			this.chatFolderId = input.readInt();
			if (input.readBoolean()) {
				byte[] nameTmp = new byte[input.readInt()];
				input.readFully(nameTmp);
				this.name = new String(nameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				this.chatIds = new long[input.readInt()];
				for (int i = 0; i < this.chatIds.length; i++) {
					this.chatIds[i] = input.readLong();
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CreateChatFolderInviteLink.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CreateChatFolderInviteLink.CONSTRUCTOR);
			output.writeInt(this.chatFolderId);
			if (this.name == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nameTmp = this.name.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nameTmp.length);
				output.write(nameTmp);
			}
			if (this.chatIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.chatIds.length);
				for (int i = 0; i < this.chatIds.length; i++) {
					output.writeLong(this.chatIds[i]);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CreateChatFolderInviteLink createChatFolderInviteLink = (CreateChatFolderInviteLink) o;
			if (this.chatFolderId != createChatFolderInviteLink.chatFolderId) {
				return false;
			}
			if (this.name != createChatFolderInviteLink.name) {
				return false;
			}
			if (!Arrays.equals(this.chatIds, createChatFolderInviteLink.chatIds)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.chatFolderId);
			result = result * 31 + (this.name == null ? 0 : this.name.hashCode());
			result = result * 31 + (Arrays.hashCode(this.chatIds));
			return result;
		}
	}

	/**
	 * Creates a new invite link for a chat. Available for basic groups,
	 * supergroups, and channels. Requires administrator privileges and
	 * canInviteUsers right in the chat.
	 * <p> Returns {@link ChatInviteLink ChatInviteLink} </p>
	**/
	public static final class CreateChatInviteLink extends Function<ChatInviteLink> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Invite link name; 0-32 characters.
		**/
		public String name;

		/**
		 * Point in time (Unix timestamp) when the link will expire; pass 0 if never.
		**/
		public int expirationDate;

		/**
		 * The maximum number of chat members that can join the chat via the link simultaneously; 0-99999; pass 0 if not limited.
		**/
		public int memberLimit;

		/**
		 * Pass true if users joining the chat via the link need to be approved by chat administrators. In this case, memberLimit must be 0.
		**/
		public boolean createsJoinRequest;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 287744833;

		/**
		 * Creates a new invite link for a chat. Available for basic groups, supergroups, and channels. Requires administrator privileges and canInviteUsers right in the chat.
		 *
		 * <p> Returns {@link ChatInviteLink ChatInviteLink} </p>
		**/
		public CreateChatInviteLink() {}

		/**
		 * Creates a new invite link for a chat. Available for basic groups, supergroups, and channels. Requires administrator privileges and canInviteUsers right in the chat.
		 *
		 * <p> Returns {@link ChatInviteLink ChatInviteLink} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param name Invite link name; 0-32 characters.
		 * @param expirationDate Point in time (Unix timestamp) when the link will expire; pass 0 if never.
		 * @param memberLimit The maximum number of chat members that can join the chat via the link simultaneously; 0-99999; pass 0 if not limited.
		 * @param createsJoinRequest Pass true if users joining the chat via the link need to be approved by chat administrators. In this case, memberLimit must be 0.
		 *
		 * <p> Returns {@link ChatInviteLink ChatInviteLink} </p>
		**/
		public CreateChatInviteLink(long chatId,
				String name,
				int expirationDate,
				int memberLimit,
				boolean createsJoinRequest) {
			this.chatId = chatId;
			this.name = name;
			this.expirationDate = expirationDate;
			this.memberLimit = memberLimit;
			this.createsJoinRequest = createsJoinRequest;
		}

		/**
		 * Creates a new invite link for a chat. Available for basic groups, supergroups, and channels. Requires administrator privileges and canInviteUsers right in the chat.
		 *
		 * <p> Returns {@link ChatInviteLink ChatInviteLink} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CreateChatInviteLink(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				byte[] nameTmp = new byte[input.readInt()];
				input.readFully(nameTmp);
				this.name = new String(nameTmp, StandardCharsets.UTF_8);
			}
			this.expirationDate = input.readInt();
			this.memberLimit = input.readInt();
			this.createsJoinRequest = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CreateChatInviteLink.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CreateChatInviteLink.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.name == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nameTmp = this.name.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nameTmp.length);
				output.write(nameTmp);
			}
			output.writeInt(this.expirationDate);
			output.writeInt(this.memberLimit);
			output.writeBoolean(this.createsJoinRequest);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CreateChatInviteLink createChatInviteLink = (CreateChatInviteLink) o;
			if (this.chatId != createChatInviteLink.chatId) {
				return false;
			}
			if (this.name != createChatInviteLink.name) {
				return false;
			}
			if (this.expirationDate != createChatInviteLink.expirationDate) {
				return false;
			}
			if (this.memberLimit != createChatInviteLink.memberLimit) {
				return false;
			}
			if (this.createsJoinRequest != createChatInviteLink.createsJoinRequest) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.name == null ? 0 : this.name.hashCode());
			return result;
		}
	}

	/**
	 * Creates a topic in a forum supergroup chat; requires canManageTopics
	 * rights in the supergroup.
	 * <p> Returns {@link ForumTopicInfo ForumTopicInfo} </p>
	**/
	public static final class CreateForumTopic extends Function<ForumTopicInfo> {


		/**
		 * Identifier of the chat.
		**/
		public long chatId;

		/**
		 * Name of the topic; 1-128 characters.
		**/
		public String name;

		/**
		 * Icon of the topic. Icon color must be one of 0x6FB9F0, 0xFFD67E, 0xCB86DB, 0x8EEE98, 0xFF93B2, or 0xFB6F5F. Telegram Premium users can use any custom emoji as topic icon, other users can use only a custom emoji returned by getForumTopicDefaultIcons.
		**/
		public ForumTopicIcon icon;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1040570140;

		/**
		 * Creates a topic in a forum supergroup chat; requires canManageTopics rights in the supergroup.
		 *
		 * <p> Returns {@link ForumTopicInfo ForumTopicInfo} </p>
		**/
		public CreateForumTopic() {}

		/**
		 * Creates a topic in a forum supergroup chat; requires canManageTopics rights in the supergroup.
		 *
		 * <p> Returns {@link ForumTopicInfo ForumTopicInfo} </p>
		 *
		 * @param chatId Identifier of the chat.
		 * @param name Name of the topic; 1-128 characters.
		 * @param icon Icon of the topic. Icon color must be one of 0x6FB9F0, 0xFFD67E, 0xCB86DB, 0x8EEE98, 0xFF93B2, or 0xFB6F5F. Telegram Premium users can use any custom emoji as topic icon, other users can use only a custom emoji returned by getForumTopicDefaultIcons.
		 *
		 * <p> Returns {@link ForumTopicInfo ForumTopicInfo} </p>
		**/
		public CreateForumTopic(long chatId, String name, ForumTopicIcon icon) {
			this.chatId = chatId;
			this.name = name;
			this.icon = icon;
		}

		/**
		 * Creates a topic in a forum supergroup chat; requires canManageTopics rights in the supergroup.
		 *
		 * <p> Returns {@link ForumTopicInfo ForumTopicInfo} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CreateForumTopic(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				byte[] nameTmp = new byte[input.readInt()];
				input.readFully(nameTmp);
				this.name = new String(nameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (ForumTopicIcon.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.icon = new ForumTopicIcon(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CreateForumTopic.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CreateForumTopic.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.name == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nameTmp = this.name.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nameTmp.length);
				output.write(nameTmp);
			}
			if (this.icon == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.icon.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CreateForumTopic createForumTopic = (CreateForumTopic) o;
			if (this.chatId != createForumTopic.chatId) {
				return false;
			}
			if (this.name != createForumTopic.name) {
				return false;
			}
			if (!Objects.equals(this.icon, createForumTopic.icon)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.name == null ? 0 : this.name.hashCode());
			result = result * 31 + (this.icon == null ? 0 : this.icon.hashCode());
			return result;
		}
	}

	/**
	 * Creates a link for the given invoice; for bots only.
	 * <p> Returns {@link HttpUrl HttpUrl} </p>
	**/
	public static final class CreateInvoiceLink extends Function<HttpUrl> {


		/**
		 * Information about the invoice of the type inputMessageInvoice.
		**/
		public InputMessageContent invoice;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 216787233;

		/**
		 * Creates a link for the given invoice; for bots only.
		 *
		 * <p> Returns {@link HttpUrl HttpUrl} </p>
		**/
		public CreateInvoiceLink() {}

		/**
		 * Creates a link for the given invoice; for bots only.
		 *
		 * <p> Returns {@link HttpUrl HttpUrl} </p>
		 *
		 * @param invoice Information about the invoice of the type inputMessageInvoice.
		 *
		 * <p> Returns {@link HttpUrl HttpUrl} </p>
		**/
		public CreateInvoiceLink(InputMessageContent invoice) {
			this.invoice = invoice;
		}

		/**
		 * Creates a link for the given invoice; for bots only.
		 *
		 * <p> Returns {@link HttpUrl HttpUrl} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CreateInvoiceLink(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputMessageText.CONSTRUCTOR: this.invoice = new InputMessageText(input); break;
					case InputMessageAnimation.CONSTRUCTOR: this.invoice = new InputMessageAnimation(input); break;
					case InputMessageAudio.CONSTRUCTOR: this.invoice = new InputMessageAudio(input); break;
					case InputMessageDocument.CONSTRUCTOR: this.invoice = new InputMessageDocument(input); break;
					case InputMessagePhoto.CONSTRUCTOR: this.invoice = new InputMessagePhoto(input); break;
					case InputMessageSticker.CONSTRUCTOR: this.invoice = new InputMessageSticker(input); break;
					case InputMessageVideo.CONSTRUCTOR: this.invoice = new InputMessageVideo(input); break;
					case InputMessageVideoNote.CONSTRUCTOR: this.invoice = new InputMessageVideoNote(input); break;
					case InputMessageVoiceNote.CONSTRUCTOR: this.invoice = new InputMessageVoiceNote(input); break;
					case InputMessageLocation.CONSTRUCTOR: this.invoice = new InputMessageLocation(input); break;
					case InputMessageVenue.CONSTRUCTOR: this.invoice = new InputMessageVenue(input); break;
					case InputMessageContact.CONSTRUCTOR: this.invoice = new InputMessageContact(input); break;
					case InputMessageDice.CONSTRUCTOR: this.invoice = new InputMessageDice(input); break;
					case InputMessageGame.CONSTRUCTOR: this.invoice = new InputMessageGame(input); break;
					case InputMessageInvoice.CONSTRUCTOR: this.invoice = new InputMessageInvoice(input); break;
					case InputMessagePoll.CONSTRUCTOR: this.invoice = new InputMessagePoll(input); break;
					case InputMessageForwarded.CONSTRUCTOR: this.invoice = new InputMessageForwarded(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CreateInvoiceLink.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CreateInvoiceLink.CONSTRUCTOR);
			if (this.invoice == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.invoice.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CreateInvoiceLink createInvoiceLink = (CreateInvoiceLink) o;
			if (!Objects.equals(this.invoice, createInvoiceLink.invoice)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.invoice == null ? 0 : this.invoice.hashCode();
		}
	}

	/**
	 * Creates a new basic group and sends a corresponding
	 * messageBasicGroupChatCreate. Returns the newly created chat.
	 * <p> Returns {@link Chat Chat} </p>
	**/
	public static final class CreateNewBasicGroupChat extends Function<Chat> {


		/**
		 * Identifiers of users to be added to the basic group; may be empty to create a basic group without other members.
		**/
		public long[] userIds;

		/**
		 * Title of the new basic group; 1-128 characters.
		**/
		public String title;

		/**
		 * Message auto-delete time value, in seconds; must be from 0 up to 365 * 86400 and be divisible by 86400. If 0, then messages aren&#039;t deleted automatically.
		**/
		public int messageAutoDeleteTime;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 624404360;

		/**
		 * Creates a new basic group and sends a corresponding messageBasicGroupChatCreate. Returns the newly created chat.
		 *
		 * <p> Returns {@link Chat Chat} </p>
		**/
		public CreateNewBasicGroupChat() {}

		/**
		 * Creates a new basic group and sends a corresponding messageBasicGroupChatCreate. Returns the newly created chat.
		 *
		 * <p> Returns {@link Chat Chat} </p>
		 *
		 * @param userIds Identifiers of users to be added to the basic group; may be empty to create a basic group without other members.
		 * @param title Title of the new basic group; 1-128 characters.
		 * @param messageAutoDeleteTime Message auto-delete time value, in seconds; must be from 0 up to 365 * 86400 and be divisible by 86400. If 0, then messages aren&#039;t deleted automatically.
		 *
		 * <p> Returns {@link Chat Chat} </p>
		**/
		public CreateNewBasicGroupChat(long[] userIds, String title, int messageAutoDeleteTime) {
			this.userIds = userIds;
			this.title = title;
			this.messageAutoDeleteTime = messageAutoDeleteTime;
		}

		/**
		 * Creates a new basic group and sends a corresponding messageBasicGroupChatCreate. Returns the newly created chat.
		 *
		 * <p> Returns {@link Chat Chat} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CreateNewBasicGroupChat(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.userIds = new long[input.readInt()];
				for (int i = 0; i < this.userIds.length; i++) {
					this.userIds[i] = input.readLong();
				}
			}
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
			this.messageAutoDeleteTime = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CreateNewBasicGroupChat.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CreateNewBasicGroupChat.CONSTRUCTOR);
			if (this.userIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.userIds.length);
				for (int i = 0; i < this.userIds.length; i++) {
					output.writeLong(this.userIds[i]);
				}
			}
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
			output.writeInt(this.messageAutoDeleteTime);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CreateNewBasicGroupChat createNewBasicGroupChat = (CreateNewBasicGroupChat) o;
			if (!Arrays.equals(this.userIds, createNewBasicGroupChat.userIds)) {
				return false;
			}
			if (this.title != createNewBasicGroupChat.title) {
				return false;
			}
			if (this.messageAutoDeleteTime != createNewBasicGroupChat.messageAutoDeleteTime) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.messageAutoDeleteTime);
			result = result * 31 + (Arrays.hashCode(this.userIds));
			result = result * 31 + (this.title == null ? 0 : this.title.hashCode());
			return result;
		}
	}

	/**
	 * Creates a new secret chat. Returns the newly created chat.
	 * <p> Returns {@link Chat Chat} </p>
	**/
	public static final class CreateNewSecretChat extends Function<Chat> {


		/**
		 * Identifier of the target user.
		**/
		public long userId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -620682651;

		/**
		 * Creates a new secret chat. Returns the newly created chat.
		 *
		 * <p> Returns {@link Chat Chat} </p>
		**/
		public CreateNewSecretChat() {}

		/**
		 * Creates a new secret chat. Returns the newly created chat.
		 *
		 * <p> Returns {@link Chat Chat} </p>
		 *
		 * @param userId Identifier of the target user.
		 *
		 * <p> Returns {@link Chat Chat} </p>
		**/
		public CreateNewSecretChat(long userId) {
			this.userId = userId;
		}

		/**
		 * Creates a new secret chat. Returns the newly created chat.
		 *
		 * <p> Returns {@link Chat Chat} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CreateNewSecretChat(DataInput input) throws IOException {
			this.userId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CreateNewSecretChat.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CreateNewSecretChat.CONSTRUCTOR);
			output.writeLong(this.userId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CreateNewSecretChat createNewSecretChat = (CreateNewSecretChat) o;
			if (this.userId != createNewSecretChat.userId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.userId);
		}
	}

	/**
	 * Creates a new sticker set. Returns the newly created sticker set.
	 * <p> Returns {@link StickerSet StickerSet} </p>
	**/
	public static final class CreateNewStickerSet extends Function<StickerSet> {


		/**
		 * Sticker set owner; ignored for regular users.
		**/
		public long userId;

		/**
		 * Sticker set title; 1-64 characters.
		**/
		public String title;

		/**
		 * Sticker set name. Can contain only English letters, digits and underscores. Must end with *&quot;_by_&lt;bot username&gt;&quot;* (*&lt;botUsername&gt;* is case insensitive) for bots; 1-64 characters.
		**/
		public String name;

		/**
		 * Format of the stickers in the set.
		**/
		public StickerFormat stickerFormat;

		/**
		 * Type of the stickers in the set.
		**/
		public StickerType stickerType;

		/**
		 * Pass true if stickers in the sticker set must be repainted; for custom emoji sticker sets only.
		**/
		public boolean needsRepainting;

		/**
		 * List of stickers to be added to the set; must be non-empty. All stickers must have the same format. For TGS stickers, uploadStickerFile must be used before the sticker is shown.
		**/
		public InputSticker[] stickers;

		/**
		 * Source of the sticker set; may be empty if unknown.
		**/
		public String source;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1057318406;

		/**
		 * Creates a new sticker set. Returns the newly created sticker set.
		 *
		 * <p> Returns {@link StickerSet StickerSet} </p>
		**/
		public CreateNewStickerSet() {}

		/**
		 * Creates a new sticker set. Returns the newly created sticker set.
		 *
		 * <p> Returns {@link StickerSet StickerSet} </p>
		 *
		 * @param userId Sticker set owner; ignored for regular users.
		 * @param title Sticker set title; 1-64 characters.
		 * @param name Sticker set name. Can contain only English letters, digits and underscores. Must end with *&quot;_by_&lt;bot username&gt;&quot;* (*&lt;botUsername&gt;* is case insensitive) for bots; 1-64 characters.
		 * @param stickerFormat Format of the stickers in the set.
		 * @param stickerType Type of the stickers in the set.
		 * @param needsRepainting Pass true if stickers in the sticker set must be repainted; for custom emoji sticker sets only.
		 * @param stickers List of stickers to be added to the set; must be non-empty. All stickers must have the same format. For TGS stickers, uploadStickerFile must be used before the sticker is shown.
		 * @param source Source of the sticker set; may be empty if unknown.
		 *
		 * <p> Returns {@link StickerSet StickerSet} </p>
		**/
		public CreateNewStickerSet(long userId,
				String title,
				String name,
				StickerFormat stickerFormat,
				StickerType stickerType,
				boolean needsRepainting,
				InputSticker[] stickers,
				String source) {
			this.userId = userId;
			this.title = title;
			this.name = name;
			this.stickerFormat = stickerFormat;
			this.stickerType = stickerType;
			this.needsRepainting = needsRepainting;
			this.stickers = stickers;
			this.source = source;
		}

		/**
		 * Creates a new sticker set. Returns the newly created sticker set.
		 *
		 * <p> Returns {@link StickerSet StickerSet} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CreateNewStickerSet(DataInput input) throws IOException {
			this.userId = input.readLong();
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] nameTmp = new byte[input.readInt()];
				input.readFully(nameTmp);
				this.name = new String(nameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case StickerFormatWebp.CONSTRUCTOR: this.stickerFormat = new StickerFormatWebp(input); break;
					case StickerFormatTgs.CONSTRUCTOR: this.stickerFormat = new StickerFormatTgs(input); break;
					case StickerFormatWebm.CONSTRUCTOR: this.stickerFormat = new StickerFormatWebm(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case StickerTypeRegular.CONSTRUCTOR: this.stickerType = new StickerTypeRegular(input); break;
					case StickerTypeMask.CONSTRUCTOR: this.stickerType = new StickerTypeMask(input); break;
					case StickerTypeCustomEmoji.CONSTRUCTOR: this.stickerType = new StickerTypeCustomEmoji(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.needsRepainting = input.readBoolean();
			if (input.readBoolean()) {
				this.stickers = new InputSticker[input.readInt()];
				for (int i = 0; i < this.stickers.length; i++) {
					if (InputSticker.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.stickers[i] = new InputSticker(input);
				}
			}
			if (input.readBoolean()) {
				byte[] sourceTmp = new byte[input.readInt()];
				input.readFully(sourceTmp);
				this.source = new String(sourceTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CreateNewStickerSet.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CreateNewStickerSet.CONSTRUCTOR);
			output.writeLong(this.userId);
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
			if (this.name == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nameTmp = this.name.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nameTmp.length);
				output.write(nameTmp);
			}
			if (this.stickerFormat == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.stickerFormat.serialize(output);
			}
			if (this.stickerType == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.stickerType.serialize(output);
			}
			output.writeBoolean(this.needsRepainting);
			if (this.stickers == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.stickers.length);
				for (int i = 0; i < this.stickers.length; i++) {
					this.stickers[i].serialize(output);
				}
			}
			if (this.source == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] sourceTmp = this.source.getBytes(StandardCharsets.UTF_8);
				output.writeInt(sourceTmp.length);
				output.write(sourceTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CreateNewStickerSet createNewStickerSet = (CreateNewStickerSet) o;
			if (this.userId != createNewStickerSet.userId) {
				return false;
			}
			if (this.title != createNewStickerSet.title) {
				return false;
			}
			if (this.name != createNewStickerSet.name) {
				return false;
			}
			if (!Objects.equals(this.stickerFormat, createNewStickerSet.stickerFormat)) {
				return false;
			}
			if (!Objects.equals(this.stickerType, createNewStickerSet.stickerType)) {
				return false;
			}
			if (this.needsRepainting != createNewStickerSet.needsRepainting) {
				return false;
			}
			if (!Arrays.equals(this.stickers, createNewStickerSet.stickers)) {
				return false;
			}
			if (this.source != createNewStickerSet.source) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.userId);
			result = result * 31 + (this.title == null ? 0 : this.title.hashCode());
			result = result * 31 + (this.name == null ? 0 : this.name.hashCode());
			result = result * 31 + (this.stickerFormat == null ? 0 : this.stickerFormat.hashCode());
			result = result * 31 + (this.stickerType == null ? 0 : this.stickerType.hashCode());
			result = result * 31 + (Arrays.hashCode(this.stickers));
			result = result * 31 + (this.source == null ? 0 : this.source.hashCode());
			return result;
		}
	}

	/**
	 * Creates a new supergroup or channel and sends a corresponding
	 * messageSupergroupChatCreate. Returns the newly created chat.
	 * <p> Returns {@link Chat Chat} </p>
	**/
	public static final class CreateNewSupergroupChat extends Function<Chat> {


		/**
		 * Title of the new chat; 1-128 characters.
		**/
		public String title;

		/**
		 * Pass true to create a forum supergroup chat.
		**/
		public boolean isForum;

		/**
		 * Pass true to create a channel chat; ignored if a forum is created.
		**/
		public boolean isChannel;

		/**
		 * Chat description; 0-255 characters.
		**/
		public String description;

		/**
		 * Chat location if a location-based supergroup is being created; pass null to create an ordinary supergroup chat.
		**/
		public ChatLocation location;

		/**
		 * Message auto-delete time value, in seconds; must be from 0 up to 365 * 86400 and be divisible by 86400. If 0, then messages aren&#039;t deleted automatically.
		**/
		public int messageAutoDeleteTime;

		/**
		 * Pass true to create a supergroup for importing messages using importMessage.
		**/
		public boolean forImport;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 804058822;

		/**
		 * Creates a new supergroup or channel and sends a corresponding messageSupergroupChatCreate. Returns the newly created chat.
		 *
		 * <p> Returns {@link Chat Chat} </p>
		**/
		public CreateNewSupergroupChat() {}

		/**
		 * Creates a new supergroup or channel and sends a corresponding messageSupergroupChatCreate. Returns the newly created chat.
		 *
		 * <p> Returns {@link Chat Chat} </p>
		 *
		 * @param title Title of the new chat; 1-128 characters.
		 * @param isForum Pass true to create a forum supergroup chat.
		 * @param isChannel Pass true to create a channel chat; ignored if a forum is created.
		 * @param description Chat description; 0-255 characters.
		 * @param location Chat location if a location-based supergroup is being created; pass null to create an ordinary supergroup chat.
		 * @param messageAutoDeleteTime Message auto-delete time value, in seconds; must be from 0 up to 365 * 86400 and be divisible by 86400. If 0, then messages aren&#039;t deleted automatically.
		 * @param forImport Pass true to create a supergroup for importing messages using importMessage.
		 *
		 * <p> Returns {@link Chat Chat} </p>
		**/
		public CreateNewSupergroupChat(String title,
				boolean isForum,
				boolean isChannel,
				String description,
				ChatLocation location,
				int messageAutoDeleteTime,
				boolean forImport) {
			this.title = title;
			this.isForum = isForum;
			this.isChannel = isChannel;
			this.description = description;
			this.location = location;
			this.messageAutoDeleteTime = messageAutoDeleteTime;
			this.forImport = forImport;
		}

		/**
		 * Creates a new supergroup or channel and sends a corresponding messageSupergroupChatCreate. Returns the newly created chat.
		 *
		 * <p> Returns {@link Chat Chat} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CreateNewSupergroupChat(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
			this.isForum = input.readBoolean();
			this.isChannel = input.readBoolean();
			if (input.readBoolean()) {
				byte[] descriptionTmp = new byte[input.readInt()];
				input.readFully(descriptionTmp);
				this.description = new String(descriptionTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (ChatLocation.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.location = new ChatLocation(input);
			}
			this.messageAutoDeleteTime = input.readInt();
			this.forImport = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CreateNewSupergroupChat.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CreateNewSupergroupChat.CONSTRUCTOR);
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
			output.writeBoolean(this.isForum);
			output.writeBoolean(this.isChannel);
			if (this.description == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] descriptionTmp = this.description.getBytes(StandardCharsets.UTF_8);
				output.writeInt(descriptionTmp.length);
				output.write(descriptionTmp);
			}
			if (this.location == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.location.serialize(output);
			}
			output.writeInt(this.messageAutoDeleteTime);
			output.writeBoolean(this.forImport);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CreateNewSupergroupChat createNewSupergroupChat = (CreateNewSupergroupChat) o;
			if (this.title != createNewSupergroupChat.title) {
				return false;
			}
			if (this.isForum != createNewSupergroupChat.isForum) {
				return false;
			}
			if (this.isChannel != createNewSupergroupChat.isChannel) {
				return false;
			}
			if (this.description != createNewSupergroupChat.description) {
				return false;
			}
			if (!Objects.equals(this.location, createNewSupergroupChat.location)) {
				return false;
			}
			if (this.messageAutoDeleteTime != createNewSupergroupChat.messageAutoDeleteTime) {
				return false;
			}
			if (this.forImport != createNewSupergroupChat.forImport) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isForum);
			result = result * 31 + (this.title == null ? 0 : this.title.hashCode());
			result = result * 31 + (this.description == null ? 0 : this.description.hashCode());
			result = result * 31 + (this.location == null ? 0 : this.location.hashCode());
			return result;
		}
	}

	/**
	 * Returns an existing chat corresponding to a given user.
	 * <p> Returns {@link Chat Chat} </p>
	**/
	public static final class CreatePrivateChat extends Function<Chat> {


		/**
		 * User identifier.
		**/
		public long userId;

		/**
		 * Pass true to create the chat without a network request. In this case all information about the chat except its type, title and photo can be incorrect.
		**/
		public boolean force;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -947758327;

		/**
		 * Returns an existing chat corresponding to a given user.
		 *
		 * <p> Returns {@link Chat Chat} </p>
		**/
		public CreatePrivateChat() {}

		/**
		 * Returns an existing chat corresponding to a given user.
		 *
		 * <p> Returns {@link Chat Chat} </p>
		 *
		 * @param userId User identifier.
		 * @param force Pass true to create the chat without a network request. In this case all information about the chat except its type, title and photo can be incorrect.
		 *
		 * <p> Returns {@link Chat Chat} </p>
		**/
		public CreatePrivateChat(long userId, boolean force) {
			this.userId = userId;
			this.force = force;
		}

		/**
		 * Returns an existing chat corresponding to a given user.
		 *
		 * <p> Returns {@link Chat Chat} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CreatePrivateChat(DataInput input) throws IOException {
			this.userId = input.readLong();
			this.force = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CreatePrivateChat.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CreatePrivateChat.CONSTRUCTOR);
			output.writeLong(this.userId);
			output.writeBoolean(this.force);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CreatePrivateChat createPrivateChat = (CreatePrivateChat) o;
			if (this.userId != createPrivateChat.userId) {
				return false;
			}
			if (this.force != createPrivateChat.force) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.userId);
			return result;
		}
	}

	/**
	 * Returns an existing chat corresponding to a known secret chat.
	 * <p> Returns {@link Chat Chat} </p>
	**/
	public static final class CreateSecretChat extends Function<Chat> {


		/**
		 * Secret chat identifier.
		**/
		public int secretChatId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1930285615;

		/**
		 * Returns an existing chat corresponding to a known secret chat.
		 *
		 * <p> Returns {@link Chat Chat} </p>
		**/
		public CreateSecretChat() {}

		/**
		 * Returns an existing chat corresponding to a known secret chat.
		 *
		 * <p> Returns {@link Chat Chat} </p>
		 *
		 * @param secretChatId Secret chat identifier.
		 *
		 * <p> Returns {@link Chat Chat} </p>
		**/
		public CreateSecretChat(int secretChatId) {
			this.secretChatId = secretChatId;
		}

		/**
		 * Returns an existing chat corresponding to a known secret chat.
		 *
		 * <p> Returns {@link Chat Chat} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CreateSecretChat(DataInput input) throws IOException {
			this.secretChatId = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CreateSecretChat.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CreateSecretChat.CONSTRUCTOR);
			output.writeInt(this.secretChatId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CreateSecretChat createSecretChat = (CreateSecretChat) o;
			if (this.secretChatId != createSecretChat.secretChatId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.secretChatId);
		}
	}

	/**
	 * Returns an existing chat corresponding to a known supergroup or
	 * channel.
	 * <p> Returns {@link Chat Chat} </p>
	**/
	public static final class CreateSupergroupChat extends Function<Chat> {


		/**
		 * Supergroup or channel identifier.
		**/
		public long supergroupId;

		/**
		 * Pass true to create the chat without a network request. In this case all information about the chat except its type, title and photo can be incorrect.
		**/
		public boolean force;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1187475691;

		/**
		 * Returns an existing chat corresponding to a known supergroup or channel.
		 *
		 * <p> Returns {@link Chat Chat} </p>
		**/
		public CreateSupergroupChat() {}

		/**
		 * Returns an existing chat corresponding to a known supergroup or channel.
		 *
		 * <p> Returns {@link Chat Chat} </p>
		 *
		 * @param supergroupId Supergroup or channel identifier.
		 * @param force Pass true to create the chat without a network request. In this case all information about the chat except its type, title and photo can be incorrect.
		 *
		 * <p> Returns {@link Chat Chat} </p>
		**/
		public CreateSupergroupChat(long supergroupId, boolean force) {
			this.supergroupId = supergroupId;
			this.force = force;
		}

		/**
		 * Returns an existing chat corresponding to a known supergroup or channel.
		 *
		 * <p> Returns {@link Chat Chat} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CreateSupergroupChat(DataInput input) throws IOException {
			this.supergroupId = input.readLong();
			this.force = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CreateSupergroupChat.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CreateSupergroupChat.CONSTRUCTOR);
			output.writeLong(this.supergroupId);
			output.writeBoolean(this.force);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CreateSupergroupChat createSupergroupChat = (CreateSupergroupChat) o;
			if (this.supergroupId != createSupergroupChat.supergroupId) {
				return false;
			}
			if (this.force != createSupergroupChat.force) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.supergroupId);
			return result;
		}
	}

	/**
	 * Creates a new temporary password for processing payments.
	 * <p> Returns {@link TemporaryPasswordState TemporaryPasswordState} </p>
	**/
	public static final class CreateTemporaryPassword extends Function<TemporaryPasswordState> {


		/**
		 * The 2-step verification password of the current user.
		**/
		public String password;

		/**
		 * Time during which the temporary password will be valid, in seconds; must be between 60 and 86400.
		**/
		public int validFor;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1626509434;

		/**
		 * Creates a new temporary password for processing payments.
		 *
		 * <p> Returns {@link TemporaryPasswordState TemporaryPasswordState} </p>
		**/
		public CreateTemporaryPassword() {}

		/**
		 * Creates a new temporary password for processing payments.
		 *
		 * <p> Returns {@link TemporaryPasswordState TemporaryPasswordState} </p>
		 *
		 * @param password The 2-step verification password of the current user.
		 * @param validFor Time during which the temporary password will be valid, in seconds; must be between 60 and 86400.
		 *
		 * <p> Returns {@link TemporaryPasswordState TemporaryPasswordState} </p>
		**/
		public CreateTemporaryPassword(String password, int validFor) {
			this.password = password;
			this.validFor = validFor;
		}

		/**
		 * Creates a new temporary password for processing payments.
		 *
		 * <p> Returns {@link TemporaryPasswordState TemporaryPasswordState} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CreateTemporaryPassword(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] passwordTmp = new byte[input.readInt()];
				input.readFully(passwordTmp);
				this.password = new String(passwordTmp, StandardCharsets.UTF_8);
			}
			this.validFor = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CreateTemporaryPassword.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CreateTemporaryPassword.CONSTRUCTOR);
			if (this.password == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] passwordTmp = this.password.getBytes(StandardCharsets.UTF_8);
				output.writeInt(passwordTmp.length);
				output.write(passwordTmp);
			}
			output.writeInt(this.validFor);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CreateTemporaryPassword createTemporaryPassword = (CreateTemporaryPassword) o;
			if (this.password != createTemporaryPassword.password) {
				return false;
			}
			if (this.validFor != createTemporaryPassword.validFor) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.validFor);
			result = result * 31 + (this.password == null ? 0 : this.password.hashCode());
			return result;
		}
	}

	/**
	 * Creates a video chat (a group call bound to a chat). Available only
	 * for basic groups, supergroups and channels; requires
	 * canManageVideoChats rights.
	 * <p> Returns {@link GroupCallId GroupCallId} </p>
	**/
	public static final class CreateVideoChat extends Function<GroupCallId> {


		/**
		 * Identifier of a chat in which the video chat will be created.
		**/
		public long chatId;

		/**
		 * Group call title; if empty, chat title will be used.
		**/
		public String title;

		/**
		 * Point in time (Unix timestamp) when the group call is supposed to be started by an administrator; 0 to start the video chat immediately. The date must be at least 10 seconds and at most 8 days in the future.
		**/
		public int startDate;

		/**
		 * Pass true to create an RTMP stream instead of an ordinary video chat; requires creator privileges.
		**/
		public boolean isRtmpStream;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2124715405;

		/**
		 * Creates a video chat (a group call bound to a chat). Available only for basic groups, supergroups and channels; requires canManageVideoChats rights.
		 *
		 * <p> Returns {@link GroupCallId GroupCallId} </p>
		**/
		public CreateVideoChat() {}

		/**
		 * Creates a video chat (a group call bound to a chat). Available only for basic groups, supergroups and channels; requires canManageVideoChats rights.
		 *
		 * <p> Returns {@link GroupCallId GroupCallId} </p>
		 *
		 * @param chatId Identifier of a chat in which the video chat will be created.
		 * @param title Group call title; if empty, chat title will be used.
		 * @param startDate Point in time (Unix timestamp) when the group call is supposed to be started by an administrator; 0 to start the video chat immediately. The date must be at least 10 seconds and at most 8 days in the future.
		 * @param isRtmpStream Pass true to create an RTMP stream instead of an ordinary video chat; requires creator privileges.
		 *
		 * <p> Returns {@link GroupCallId GroupCallId} </p>
		**/
		public CreateVideoChat(long chatId,
				String title,
				int startDate,
				boolean isRtmpStream) {
			this.chatId = chatId;
			this.title = title;
			this.startDate = startDate;
			this.isRtmpStream = isRtmpStream;
		}

		/**
		 * Creates a video chat (a group call bound to a chat). Available only for basic groups, supergroups and channels; requires canManageVideoChats rights.
		 *
		 * <p> Returns {@link GroupCallId GroupCallId} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public CreateVideoChat(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
			this.startDate = input.readInt();
			this.isRtmpStream = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return CreateVideoChat.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(CreateVideoChat.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
			output.writeInt(this.startDate);
			output.writeBoolean(this.isRtmpStream);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			CreateVideoChat createVideoChat = (CreateVideoChat) o;
			if (this.chatId != createVideoChat.chatId) {
				return false;
			}
			if (this.title != createVideoChat.title) {
				return false;
			}
			if (this.startDate != createVideoChat.startDate) {
				return false;
			}
			if (this.isRtmpStream != createVideoChat.isRtmpStream) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.title == null ? 0 : this.title.hashCode());
			return result;
		}
	}

	/**
	 * Deletes the account of the current user, deleting all information
	 * associated with the user from the server. The phone number of the
	 * account can be used to create a new account. Can be called before
	 * authorization when the current authorization state is
	 * authorizationStateWaitPassword.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class DeleteAccount extends Function<Ok> {


		/**
		 * The reason why the account was deleted; optional.
		**/
		public String reason;

		/**
		 * The 2-step verification password of the current user. If not specified, account deletion can be canceled within one week.
		**/
		public String password;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1395816134;

		/**
		 * Deletes the account of the current user, deleting all information associated with the user from the server. The phone number of the account can be used to create a new account. Can be called before authorization when the current authorization state is authorizationStateWaitPassword.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public DeleteAccount() {}

		/**
		 * Deletes the account of the current user, deleting all information associated with the user from the server. The phone number of the account can be used to create a new account. Can be called before authorization when the current authorization state is authorizationStateWaitPassword.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param reason The reason why the account was deleted; optional.
		 * @param password The 2-step verification password of the current user. If not specified, account deletion can be canceled within one week.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public DeleteAccount(String reason, String password) {
			this.reason = reason;
			this.password = password;
		}

		/**
		 * Deletes the account of the current user, deleting all information associated with the user from the server. The phone number of the account can be used to create a new account. Can be called before authorization when the current authorization state is authorizationStateWaitPassword.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public DeleteAccount(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] reasonTmp = new byte[input.readInt()];
				input.readFully(reasonTmp);
				this.reason = new String(reasonTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] passwordTmp = new byte[input.readInt()];
				input.readFully(passwordTmp);
				this.password = new String(passwordTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return DeleteAccount.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(DeleteAccount.CONSTRUCTOR);
			if (this.reason == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] reasonTmp = this.reason.getBytes(StandardCharsets.UTF_8);
				output.writeInt(reasonTmp.length);
				output.write(reasonTmp);
			}
			if (this.password == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] passwordTmp = this.password.getBytes(StandardCharsets.UTF_8);
				output.writeInt(passwordTmp.length);
				output.write(passwordTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			DeleteAccount deleteAccount = (DeleteAccount) o;
			if (this.reason != deleteAccount.reason) {
				return false;
			}
			if (this.password != deleteAccount.password) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.reason == null ? 0 : this.reason.hashCode();
			result = result * 31 + (this.password == null ? 0 : this.password.hashCode());
			return result;
		}
	}

	/**
	 * Deletes all call messages.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class DeleteAllCallMessages extends Function<Ok> {


		/**
		 * Pass true to delete the messages for all users.
		**/
		public boolean revoke;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1466445325;

		/**
		 * Deletes all call messages.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public DeleteAllCallMessages() {}

		/**
		 * Deletes all call messages.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param revoke Pass true to delete the messages for all users.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public DeleteAllCallMessages(boolean revoke) {
			this.revoke = revoke;
		}

		/**
		 * Deletes all call messages.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public DeleteAllCallMessages(DataInput input) throws IOException {
			this.revoke = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return DeleteAllCallMessages.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(DeleteAllCallMessages.CONSTRUCTOR);
			output.writeBoolean(this.revoke);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			DeleteAllCallMessages deleteAllCallMessages = (DeleteAllCallMessages) o;
			if (this.revoke != deleteAllCallMessages.revoke) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Boolean.hashCode(this.revoke);
		}
	}

	/**
	 * Deletes all revoked chat invite links created by a given chat
	 * administrator. Requires administrator privileges and canInviteUsers
	 * right in the chat for own links and owner privileges for other links.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class DeleteAllRevokedChatInviteLinks extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * User identifier of a chat administrator, which links will be deleted. Must be an identifier of the current user for non-owner.
		**/
		public long creatorUserId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1112020698;

		/**
		 * Deletes all revoked chat invite links created by a given chat administrator. Requires administrator privileges and canInviteUsers right in the chat for own links and owner privileges for other links.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public DeleteAllRevokedChatInviteLinks() {}

		/**
		 * Deletes all revoked chat invite links created by a given chat administrator. Requires administrator privileges and canInviteUsers right in the chat for own links and owner privileges for other links.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param creatorUserId User identifier of a chat administrator, which links will be deleted. Must be an identifier of the current user for non-owner.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public DeleteAllRevokedChatInviteLinks(long chatId, long creatorUserId) {
			this.chatId = chatId;
			this.creatorUserId = creatorUserId;
		}

		/**
		 * Deletes all revoked chat invite links created by a given chat administrator. Requires administrator privileges and canInviteUsers right in the chat for own links and owner privileges for other links.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public DeleteAllRevokedChatInviteLinks(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.creatorUserId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return DeleteAllRevokedChatInviteLinks.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(DeleteAllRevokedChatInviteLinks.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.creatorUserId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			DeleteAllRevokedChatInviteLinks deleteAllRevokedChatInviteLinks = (DeleteAllRevokedChatInviteLinks) o;
			if (this.chatId != deleteAllRevokedChatInviteLinks.chatId) {
				return false;
			}
			if (this.creatorUserId != deleteAllRevokedChatInviteLinks.creatorUserId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Deletes a chat along with all messages in the corresponding chat for
	 * all chat members. For group chats this will release the usernames and
	 * remove all members. Use the field chat.canBeDeletedForAllUsers to
	 * find whether the method can be applied to the chat.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class DeleteChat extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -171253666;

		/**
		 * Deletes a chat along with all messages in the corresponding chat for all chat members. For group chats this will release the usernames and remove all members. Use the field chat.canBeDeletedForAllUsers to find whether the method can be applied to the chat.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public DeleteChat() {}

		/**
		 * Deletes a chat along with all messages in the corresponding chat for all chat members. For group chats this will release the usernames and remove all members. Use the field chat.canBeDeletedForAllUsers to find whether the method can be applied to the chat.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public DeleteChat(long chatId) {
			this.chatId = chatId;
		}

		/**
		 * Deletes a chat along with all messages in the corresponding chat for all chat members. For group chats this will release the usernames and remove all members. Use the field chat.canBeDeletedForAllUsers to find whether the method can be applied to the chat.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public DeleteChat(DataInput input) throws IOException {
			this.chatId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return DeleteChat.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(DeleteChat.CONSTRUCTOR);
			output.writeLong(this.chatId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			DeleteChat deleteChat = (DeleteChat) o;
			if (this.chatId != deleteChat.chatId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.chatId);
		}
	}

	/**
	 * Deletes existing chat folder.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class DeleteChatFolder extends Function<Ok> {


		/**
		 * Chat folder identifier.
		**/
		public int chatFolderId;

		/**
		 * Identifiers of the chats to leave. The chats must be pinned or always included in the folder.
		**/
		public long[] leaveChatIds;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1956364551;

		/**
		 * Deletes existing chat folder.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public DeleteChatFolder() {}

		/**
		 * Deletes existing chat folder.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatFolderId Chat folder identifier.
		 * @param leaveChatIds Identifiers of the chats to leave. The chats must be pinned or always included in the folder.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public DeleteChatFolder(int chatFolderId, long[] leaveChatIds) {
			this.chatFolderId = chatFolderId;
			this.leaveChatIds = leaveChatIds;
		}

		/**
		 * Deletes existing chat folder.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public DeleteChatFolder(DataInput input) throws IOException {
			this.chatFolderId = input.readInt();
			if (input.readBoolean()) {
				this.leaveChatIds = new long[input.readInt()];
				for (int i = 0; i < this.leaveChatIds.length; i++) {
					this.leaveChatIds[i] = input.readLong();
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return DeleteChatFolder.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(DeleteChatFolder.CONSTRUCTOR);
			output.writeInt(this.chatFolderId);
			if (this.leaveChatIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.leaveChatIds.length);
				for (int i = 0; i < this.leaveChatIds.length; i++) {
					output.writeLong(this.leaveChatIds[i]);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			DeleteChatFolder deleteChatFolder = (DeleteChatFolder) o;
			if (this.chatFolderId != deleteChatFolder.chatFolderId) {
				return false;
			}
			if (!Arrays.equals(this.leaveChatIds, deleteChatFolder.leaveChatIds)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.chatFolderId);
			result = result * 31 + (Arrays.hashCode(this.leaveChatIds));
			return result;
		}
	}

	/**
	 * Deletes an invite link for a chat folder.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class DeleteChatFolderInviteLink extends Function<Ok> {


		/**
		 * Chat folder identifier.
		**/
		public int chatFolderId;

		/**
		 * Invite link to be deleted.
		**/
		public String inviteLink;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -930057858;

		/**
		 * Deletes an invite link for a chat folder.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public DeleteChatFolderInviteLink() {}

		/**
		 * Deletes an invite link for a chat folder.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatFolderId Chat folder identifier.
		 * @param inviteLink Invite link to be deleted.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public DeleteChatFolderInviteLink(int chatFolderId, String inviteLink) {
			this.chatFolderId = chatFolderId;
			this.inviteLink = inviteLink;
		}

		/**
		 * Deletes an invite link for a chat folder.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public DeleteChatFolderInviteLink(DataInput input) throws IOException {
			this.chatFolderId = input.readInt();
			if (input.readBoolean()) {
				byte[] inviteLinkTmp = new byte[input.readInt()];
				input.readFully(inviteLinkTmp);
				this.inviteLink = new String(inviteLinkTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return DeleteChatFolderInviteLink.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(DeleteChatFolderInviteLink.CONSTRUCTOR);
			output.writeInt(this.chatFolderId);
			if (this.inviteLink == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] inviteLinkTmp = this.inviteLink.getBytes(StandardCharsets.UTF_8);
				output.writeInt(inviteLinkTmp.length);
				output.write(inviteLinkTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			DeleteChatFolderInviteLink deleteChatFolderInviteLink = (DeleteChatFolderInviteLink) o;
			if (this.chatFolderId != deleteChatFolderInviteLink.chatFolderId) {
				return false;
			}
			if (this.inviteLink != deleteChatFolderInviteLink.inviteLink) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.chatFolderId);
			result = result * 31 + (this.inviteLink == null ? 0 : this.inviteLink.hashCode());
			return result;
		}
	}

	/**
	 * Deletes all messages in the chat. Use chat.canBeDeletedOnlyForSelf
	 * and chat.canBeDeletedForAllUsers fields to find whether and how the
	 * method can be applied to the chat.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class DeleteChatHistory extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Pass true to remove the chat from all chat lists.
		**/
		public boolean removeFromChatList;

		/**
		 * Pass true to delete chat history for all users.
		**/
		public boolean revoke;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1472081761;

		/**
		 * Deletes all messages in the chat. Use chat.canBeDeletedOnlyForSelf and chat.canBeDeletedForAllUsers fields to find whether and how the method can be applied to the chat.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public DeleteChatHistory() {}

		/**
		 * Deletes all messages in the chat. Use chat.canBeDeletedOnlyForSelf and chat.canBeDeletedForAllUsers fields to find whether and how the method can be applied to the chat.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param removeFromChatList Pass true to remove the chat from all chat lists.
		 * @param revoke Pass true to delete chat history for all users.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public DeleteChatHistory(long chatId, boolean removeFromChatList, boolean revoke) {
			this.chatId = chatId;
			this.removeFromChatList = removeFromChatList;
			this.revoke = revoke;
		}

		/**
		 * Deletes all messages in the chat. Use chat.canBeDeletedOnlyForSelf and chat.canBeDeletedForAllUsers fields to find whether and how the method can be applied to the chat.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public DeleteChatHistory(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.removeFromChatList = input.readBoolean();
			this.revoke = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return DeleteChatHistory.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(DeleteChatHistory.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeBoolean(this.removeFromChatList);
			output.writeBoolean(this.revoke);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			DeleteChatHistory deleteChatHistory = (DeleteChatHistory) o;
			if (this.chatId != deleteChatHistory.chatId) {
				return false;
			}
			if (this.removeFromChatList != deleteChatHistory.removeFromChatList) {
				return false;
			}
			if (this.revoke != deleteChatHistory.revoke) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Deletes all messages between the specified dates in a chat. Supported
	 * only for private chats and basic groups. Messages sent in the last 30
	 * seconds will not be deleted.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class DeleteChatMessagesByDate extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * The minimum date of the messages to delete.
		**/
		public int minDate;

		/**
		 * The maximum date of the messages to delete.
		**/
		public int maxDate;

		/**
		 * Pass true to delete chat messages for all users; private chats only.
		**/
		public boolean revoke;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1639653185;

		/**
		 * Deletes all messages between the specified dates in a chat. Supported only for private chats and basic groups. Messages sent in the last 30 seconds will not be deleted.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public DeleteChatMessagesByDate() {}

		/**
		 * Deletes all messages between the specified dates in a chat. Supported only for private chats and basic groups. Messages sent in the last 30 seconds will not be deleted.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param minDate The minimum date of the messages to delete.
		 * @param maxDate The maximum date of the messages to delete.
		 * @param revoke Pass true to delete chat messages for all users; private chats only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public DeleteChatMessagesByDate(long chatId, int minDate, int maxDate, boolean revoke) {
			this.chatId = chatId;
			this.minDate = minDate;
			this.maxDate = maxDate;
			this.revoke = revoke;
		}

		/**
		 * Deletes all messages between the specified dates in a chat. Supported only for private chats and basic groups. Messages sent in the last 30 seconds will not be deleted.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public DeleteChatMessagesByDate(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.minDate = input.readInt();
			this.maxDate = input.readInt();
			this.revoke = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return DeleteChatMessagesByDate.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(DeleteChatMessagesByDate.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeInt(this.minDate);
			output.writeInt(this.maxDate);
			output.writeBoolean(this.revoke);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			DeleteChatMessagesByDate deleteChatMessagesByDate = (DeleteChatMessagesByDate) o;
			if (this.chatId != deleteChatMessagesByDate.chatId) {
				return false;
			}
			if (this.minDate != deleteChatMessagesByDate.minDate) {
				return false;
			}
			if (this.maxDate != deleteChatMessagesByDate.maxDate) {
				return false;
			}
			if (this.revoke != deleteChatMessagesByDate.revoke) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Deletes all messages sent by the specified message sender in a chat.
	 * Supported only for supergroups; requires canDeleteMessages
	 * administrator privileges.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class DeleteChatMessagesBySender extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Identifier of the sender of messages to delete.
		**/
		public MessageSender senderId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1164235161;

		/**
		 * Deletes all messages sent by the specified message sender in a chat. Supported only for supergroups; requires canDeleteMessages administrator privileges.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public DeleteChatMessagesBySender() {}

		/**
		 * Deletes all messages sent by the specified message sender in a chat. Supported only for supergroups; requires canDeleteMessages administrator privileges.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param senderId Identifier of the sender of messages to delete.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public DeleteChatMessagesBySender(long chatId, MessageSender senderId) {
			this.chatId = chatId;
			this.senderId = senderId;
		}

		/**
		 * Deletes all messages sent by the specified message sender in a chat. Supported only for supergroups; requires canDeleteMessages administrator privileges.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public DeleteChatMessagesBySender(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case MessageSenderUser.CONSTRUCTOR: this.senderId = new MessageSenderUser(input); break;
					case MessageSenderChat.CONSTRUCTOR: this.senderId = new MessageSenderChat(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return DeleteChatMessagesBySender.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(DeleteChatMessagesBySender.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.senderId == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.senderId.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			DeleteChatMessagesBySender deleteChatMessagesBySender = (DeleteChatMessagesBySender) o;
			if (this.chatId != deleteChatMessagesBySender.chatId) {
				return false;
			}
			if (!Objects.equals(this.senderId, deleteChatMessagesBySender.senderId)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.senderId == null ? 0 : this.senderId.hashCode());
			return result;
		}
	}

	/**
	 * Deletes the default reply markup from a chat. Must be called after a
	 * one-time keyboard or a replyMarkupForceReply reply markup has been
	 * used. An updateChatReplyMarkup update will be sent if the reply
	 * markup is changed.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class DeleteChatReplyMarkup extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * The message identifier of the used keyboard.
		**/
		public long messageId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 100637531;

		/**
		 * Deletes the default reply markup from a chat. Must be called after a one-time keyboard or a replyMarkupForceReply reply markup has been used. An updateChatReplyMarkup update will be sent if the reply markup is changed.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public DeleteChatReplyMarkup() {}

		/**
		 * Deletes the default reply markup from a chat. Must be called after a one-time keyboard or a replyMarkupForceReply reply markup has been used. An updateChatReplyMarkup update will be sent if the reply markup is changed.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param messageId The message identifier of the used keyboard.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public DeleteChatReplyMarkup(long chatId, long messageId) {
			this.chatId = chatId;
			this.messageId = messageId;
		}

		/**
		 * Deletes the default reply markup from a chat. Must be called after a one-time keyboard or a replyMarkupForceReply reply markup has been used. An updateChatReplyMarkup update will be sent if the reply markup is changed.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public DeleteChatReplyMarkup(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return DeleteChatReplyMarkup.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(DeleteChatReplyMarkup.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			DeleteChatReplyMarkup deleteChatReplyMarkup = (DeleteChatReplyMarkup) o;
			if (this.chatId != deleteChatReplyMarkup.chatId) {
				return false;
			}
			if (this.messageId != deleteChatReplyMarkup.messageId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Deletes commands supported by the bot for the given user scope and
	 * language; for bots only.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class DeleteCommands extends Function<Ok> {


		/**
		 * The scope to which the commands are relevant; pass null to delete commands in the default bot command scope.
		**/
		public BotCommandScope scope;

		/**
		 * A two-letter ISO 639-1 language code or an empty string.
		**/
		public String languageCode;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1002732586;

		/**
		 * Deletes commands supported by the bot for the given user scope and language; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public DeleteCommands() {}

		/**
		 * Deletes commands supported by the bot for the given user scope and language; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param scope The scope to which the commands are relevant; pass null to delete commands in the default bot command scope.
		 * @param languageCode A two-letter ISO 639-1 language code or an empty string.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public DeleteCommands(BotCommandScope scope, String languageCode) {
			this.scope = scope;
			this.languageCode = languageCode;
		}

		/**
		 * Deletes commands supported by the bot for the given user scope and language; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public DeleteCommands(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case BotCommandScopeDefault.CONSTRUCTOR: this.scope = new BotCommandScopeDefault(input); break;
					case BotCommandScopeAllPrivateChats.CONSTRUCTOR: this.scope = new BotCommandScopeAllPrivateChats(input); break;
					case BotCommandScopeAllGroupChats.CONSTRUCTOR: this.scope = new BotCommandScopeAllGroupChats(input); break;
					case BotCommandScopeAllChatAdministrators.CONSTRUCTOR: this.scope = new BotCommandScopeAllChatAdministrators(input); break;
					case BotCommandScopeChat.CONSTRUCTOR: this.scope = new BotCommandScopeChat(input); break;
					case BotCommandScopeChatAdministrators.CONSTRUCTOR: this.scope = new BotCommandScopeChatAdministrators(input); break;
					case BotCommandScopeChatMember.CONSTRUCTOR: this.scope = new BotCommandScopeChatMember(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				byte[] languageCodeTmp = new byte[input.readInt()];
				input.readFully(languageCodeTmp);
				this.languageCode = new String(languageCodeTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return DeleteCommands.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(DeleteCommands.CONSTRUCTOR);
			if (this.scope == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.scope.serialize(output);
			}
			if (this.languageCode == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] languageCodeTmp = this.languageCode.getBytes(StandardCharsets.UTF_8);
				output.writeInt(languageCodeTmp.length);
				output.write(languageCodeTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			DeleteCommands deleteCommands = (DeleteCommands) o;
			if (!Objects.equals(this.scope, deleteCommands.scope)) {
				return false;
			}
			if (this.languageCode != deleteCommands.languageCode) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.scope == null ? 0 : this.scope.hashCode();
			result = result * 31 + (this.languageCode == null ? 0 : this.languageCode.hashCode());
			return result;
		}
	}

	/**
	 * Deletes a file from the TDLib file cache.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class DeleteFile extends Function<Ok> {


		/**
		 * Identifier of the file to delete.
		**/
		public int fileId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1807653676;

		/**
		 * Deletes a file from the TDLib file cache.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public DeleteFile() {}

		/**
		 * Deletes a file from the TDLib file cache.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param fileId Identifier of the file to delete.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public DeleteFile(int fileId) {
			this.fileId = fileId;
		}

		/**
		 * Deletes a file from the TDLib file cache.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public DeleteFile(DataInput input) throws IOException {
			this.fileId = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return DeleteFile.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(DeleteFile.CONSTRUCTOR);
			output.writeInt(this.fileId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			DeleteFile deleteFile = (DeleteFile) o;
			if (this.fileId != deleteFile.fileId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.fileId);
		}
	}

	/**
	 * Deletes all messages in a forum topic; requires canDeleteMessages
	 * administrator right in the supergroup unless the user is creator of
	 * the topic, the topic has no messages from other users and has at most
	 * 11 messages.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class DeleteForumTopic extends Function<Ok> {


		/**
		 * Identifier of the chat.
		**/
		public long chatId;

		/**
		 * Message thread identifier of the forum topic.
		**/
		public long messageThreadId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1864916152;

		/**
		 * Deletes all messages in a forum topic; requires canDeleteMessages administrator right in the supergroup unless the user is creator of the topic, the topic has no messages from other users and has at most 11 messages.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public DeleteForumTopic() {}

		/**
		 * Deletes all messages in a forum topic; requires canDeleteMessages administrator right in the supergroup unless the user is creator of the topic, the topic has no messages from other users and has at most 11 messages.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Identifier of the chat.
		 * @param messageThreadId Message thread identifier of the forum topic.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public DeleteForumTopic(long chatId, long messageThreadId) {
			this.chatId = chatId;
			this.messageThreadId = messageThreadId;
		}

		/**
		 * Deletes all messages in a forum topic; requires canDeleteMessages administrator right in the supergroup unless the user is creator of the topic, the topic has no messages from other users and has at most 11 messages.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public DeleteForumTopic(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageThreadId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return DeleteForumTopic.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(DeleteForumTopic.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageThreadId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			DeleteForumTopic deleteForumTopic = (DeleteForumTopic) o;
			if (this.chatId != deleteForumTopic.chatId) {
				return false;
			}
			if (this.messageThreadId != deleteForumTopic.messageThreadId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Deletes all information about a language pack in the current
	 * localization target. The language pack which is currently in use
	 * (including base language pack) or is being synchronized can&#039;t be
	 * deleted. Can be called before authorization.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class DeleteLanguagePack extends Function<Ok> {


		/**
		 * Identifier of the language pack to delete.
		**/
		public String languagePackId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2108761026;

		/**
		 * Deletes all information about a language pack in the current localization target. The language pack which is currently in use (including base language pack) or is being synchronized can&#039;t be deleted. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public DeleteLanguagePack() {}

		/**
		 * Deletes all information about a language pack in the current localization target. The language pack which is currently in use (including base language pack) or is being synchronized can&#039;t be deleted. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param languagePackId Identifier of the language pack to delete.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public DeleteLanguagePack(String languagePackId) {
			this.languagePackId = languagePackId;
		}

		/**
		 * Deletes all information about a language pack in the current localization target. The language pack which is currently in use (including base language pack) or is being synchronized can&#039;t be deleted. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public DeleteLanguagePack(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] languagePackIdTmp = new byte[input.readInt()];
				input.readFully(languagePackIdTmp);
				this.languagePackId = new String(languagePackIdTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return DeleteLanguagePack.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(DeleteLanguagePack.CONSTRUCTOR);
			if (this.languagePackId == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] languagePackIdTmp = this.languagePackId.getBytes(StandardCharsets.UTF_8);
				output.writeInt(languagePackIdTmp.length);
				output.write(languagePackIdTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			DeleteLanguagePack deleteLanguagePack = (DeleteLanguagePack) o;
			if (this.languagePackId != deleteLanguagePack.languagePackId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.languagePackId == null ? 0 : this.languagePackId.hashCode();
		}
	}

	/**
	 * Deletes messages.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class DeleteMessages extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Identifiers of the messages to be deleted.
		**/
		public long[] messageIds;

		/**
		 * Pass true to delete messages for all chat members. Always true for supergroups, channels and secret chats.
		**/
		public boolean revoke;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1130090173;

		/**
		 * Deletes messages.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public DeleteMessages() {}

		/**
		 * Deletes messages.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param messageIds Identifiers of the messages to be deleted.
		 * @param revoke Pass true to delete messages for all chat members. Always true for supergroups, channels and secret chats.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public DeleteMessages(long chatId, long[] messageIds, boolean revoke) {
			this.chatId = chatId;
			this.messageIds = messageIds;
			this.revoke = revoke;
		}

		/**
		 * Deletes messages.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public DeleteMessages(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				this.messageIds = new long[input.readInt()];
				for (int i = 0; i < this.messageIds.length; i++) {
					this.messageIds[i] = input.readLong();
				}
			}
			this.revoke = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return DeleteMessages.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(DeleteMessages.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.messageIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.messageIds.length);
				for (int i = 0; i < this.messageIds.length; i++) {
					output.writeLong(this.messageIds[i]);
				}
			}
			output.writeBoolean(this.revoke);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			DeleteMessages deleteMessages = (DeleteMessages) o;
			if (this.chatId != deleteMessages.chatId) {
				return false;
			}
			if (!Arrays.equals(this.messageIds, deleteMessages.messageIds)) {
				return false;
			}
			if (this.revoke != deleteMessages.revoke) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (Arrays.hashCode(this.messageIds));
			return result;
		}
	}

	/**
	 * Deletes a Telegram Passport element.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class DeletePassportElement extends Function<Ok> {


		/**
		 * Element type.
		**/
		public PassportElementType type;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1719555468;

		/**
		 * Deletes a Telegram Passport element.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public DeletePassportElement() {}

		/**
		 * Deletes a Telegram Passport element.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param type Element type.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public DeletePassportElement(PassportElementType type) {
			this.type = type;
		}

		/**
		 * Deletes a Telegram Passport element.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public DeletePassportElement(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case PassportElementTypePersonalDetails.CONSTRUCTOR: this.type = new PassportElementTypePersonalDetails(input); break;
					case PassportElementTypePassport.CONSTRUCTOR: this.type = new PassportElementTypePassport(input); break;
					case PassportElementTypeDriverLicense.CONSTRUCTOR: this.type = new PassportElementTypeDriverLicense(input); break;
					case PassportElementTypeIdentityCard.CONSTRUCTOR: this.type = new PassportElementTypeIdentityCard(input); break;
					case PassportElementTypeInternalPassport.CONSTRUCTOR: this.type = new PassportElementTypeInternalPassport(input); break;
					case PassportElementTypeAddress.CONSTRUCTOR: this.type = new PassportElementTypeAddress(input); break;
					case PassportElementTypeUtilityBill.CONSTRUCTOR: this.type = new PassportElementTypeUtilityBill(input); break;
					case PassportElementTypeBankStatement.CONSTRUCTOR: this.type = new PassportElementTypeBankStatement(input); break;
					case PassportElementTypeRentalAgreement.CONSTRUCTOR: this.type = new PassportElementTypeRentalAgreement(input); break;
					case PassportElementTypePassportRegistration.CONSTRUCTOR: this.type = new PassportElementTypePassportRegistration(input); break;
					case PassportElementTypeTemporaryRegistration.CONSTRUCTOR: this.type = new PassportElementTypeTemporaryRegistration(input); break;
					case PassportElementTypePhoneNumber.CONSTRUCTOR: this.type = new PassportElementTypePhoneNumber(input); break;
					case PassportElementTypeEmailAddress.CONSTRUCTOR: this.type = new PassportElementTypeEmailAddress(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return DeletePassportElement.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(DeletePassportElement.CONSTRUCTOR);
			if (this.type == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.type.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			DeletePassportElement deletePassportElement = (DeletePassportElement) o;
			if (!Objects.equals(this.type, deletePassportElement.type)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.type == null ? 0 : this.type.hashCode();
		}
	}

	/**
	 * Deletes a profile photo.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class DeleteProfilePhoto extends Function<Ok> {


		/**
		 * Identifier of the profile photo to delete.
		**/
		public long profilePhotoId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1319794625;

		/**
		 * Deletes a profile photo.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public DeleteProfilePhoto() {}

		/**
		 * Deletes a profile photo.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param profilePhotoId Identifier of the profile photo to delete.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public DeleteProfilePhoto(long profilePhotoId) {
			this.profilePhotoId = profilePhotoId;
		}

		/**
		 * Deletes a profile photo.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public DeleteProfilePhoto(DataInput input) throws IOException {
			this.profilePhotoId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return DeleteProfilePhoto.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(DeleteProfilePhoto.CONSTRUCTOR);
			output.writeLong(this.profilePhotoId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			DeleteProfilePhoto deleteProfilePhoto = (DeleteProfilePhoto) o;
			if (this.profilePhotoId != deleteProfilePhoto.profilePhotoId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.profilePhotoId);
		}
	}

	/**
	 * Deletes revoked chat invite links. Requires administrator privileges
	 * and canInviteUsers right in the chat for own links and owner
	 * privileges for other links.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class DeleteRevokedChatInviteLink extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Invite link to revoke.
		**/
		public String inviteLink;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1859711873;

		/**
		 * Deletes revoked chat invite links. Requires administrator privileges and canInviteUsers right in the chat for own links and owner privileges for other links.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public DeleteRevokedChatInviteLink() {}

		/**
		 * Deletes revoked chat invite links. Requires administrator privileges and canInviteUsers right in the chat for own links and owner privileges for other links.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param inviteLink Invite link to revoke.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public DeleteRevokedChatInviteLink(long chatId, String inviteLink) {
			this.chatId = chatId;
			this.inviteLink = inviteLink;
		}

		/**
		 * Deletes revoked chat invite links. Requires administrator privileges and canInviteUsers right in the chat for own links and owner privileges for other links.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public DeleteRevokedChatInviteLink(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				byte[] inviteLinkTmp = new byte[input.readInt()];
				input.readFully(inviteLinkTmp);
				this.inviteLink = new String(inviteLinkTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return DeleteRevokedChatInviteLink.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(DeleteRevokedChatInviteLink.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.inviteLink == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] inviteLinkTmp = this.inviteLink.getBytes(StandardCharsets.UTF_8);
				output.writeInt(inviteLinkTmp.length);
				output.write(inviteLinkTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			DeleteRevokedChatInviteLink deleteRevokedChatInviteLink = (DeleteRevokedChatInviteLink) o;
			if (this.chatId != deleteRevokedChatInviteLink.chatId) {
				return false;
			}
			if (this.inviteLink != deleteRevokedChatInviteLink.inviteLink) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.inviteLink == null ? 0 : this.inviteLink.hashCode());
			return result;
		}
	}

	/**
	 * Deletes saved credentials for all payment provider bots.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class DeleteSavedCredentials extends Function<Ok> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 826300114;

		/**
		 * Deletes saved credentials for all payment provider bots.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public DeleteSavedCredentials() {}

		/**
		 * Deletes saved credentials for all payment provider bots.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/

		/**
		 * Deletes saved credentials for all payment provider bots.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public DeleteSavedCredentials(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return DeleteSavedCredentials.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(DeleteSavedCredentials.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return DeleteSavedCredentials.CONSTRUCTOR;
		}
	}

	/**
	 * Deletes saved order information.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class DeleteSavedOrderInfo extends Function<Ok> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1629058164;

		/**
		 * Deletes saved order information.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public DeleteSavedOrderInfo() {}

		/**
		 * Deletes saved order information.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/

		/**
		 * Deletes saved order information.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public DeleteSavedOrderInfo(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return DeleteSavedOrderInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(DeleteSavedOrderInfo.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return DeleteSavedOrderInfo.CONSTRUCTOR;
		}
	}

	/**
	 * Deleted a sticker set; for bots only.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class DeleteStickerSet extends Function<Ok> {


		/**
		 * Sticker set name.
		**/
		public String name;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1577745325;

		/**
		 * Deleted a sticker set; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public DeleteStickerSet() {}

		/**
		 * Deleted a sticker set; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param name Sticker set name.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public DeleteStickerSet(String name) {
			this.name = name;
		}

		/**
		 * Deleted a sticker set; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public DeleteStickerSet(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] nameTmp = new byte[input.readInt()];
				input.readFully(nameTmp);
				this.name = new String(nameTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return DeleteStickerSet.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(DeleteStickerSet.CONSTRUCTOR);
			if (this.name == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nameTmp = this.name.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nameTmp.length);
				output.write(nameTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			DeleteStickerSet deleteStickerSet = (DeleteStickerSet) o;
			if (this.name != deleteStickerSet.name) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.name == null ? 0 : this.name.hashCode();
		}
	}

	/**
	 * Closes the TDLib instance, destroying all local data without a proper
	 * logout. The current user session will remain in the list of all
	 * active sessions. All local data will be destroyed. After the
	 * destruction completes updateAuthorizationState with
	 * authorizationStateClosed will be sent. Can be called before
	 * authorization.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class Destroy extends Function<Ok> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 685331274;

		/**
		 * Closes the TDLib instance, destroying all local data without a proper logout. The current user session will remain in the list of all active sessions. All local data will be destroyed. After the destruction completes updateAuthorizationState with authorizationStateClosed will be sent. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public Destroy() {}

		/**
		 * Closes the TDLib instance, destroying all local data without a proper logout. The current user session will remain in the list of all active sessions. All local data will be destroyed. After the destruction completes updateAuthorizationState with authorizationStateClosed will be sent. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/

		/**
		 * Closes the TDLib instance, destroying all local data without a proper logout. The current user session will remain in the list of all active sessions. All local data will be destroyed. After the destruction completes updateAuthorizationState with authorizationStateClosed will be sent. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public Destroy(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return Destroy.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(Destroy.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Destroy.CONSTRUCTOR;
		}
	}

	/**
	 * Disables all active non-editable usernames of a supergroup or
	 * channel, requires owner privileges in the supergroup or channel.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class DisableAllSupergroupUsernames extends Function<Ok> {


		/**
		 * Identifier of the supergroup or channel.
		**/
		public long supergroupId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 843511216;

		/**
		 * Disables all active non-editable usernames of a supergroup or channel, requires owner privileges in the supergroup or channel.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public DisableAllSupergroupUsernames() {}

		/**
		 * Disables all active non-editable usernames of a supergroup or channel, requires owner privileges in the supergroup or channel.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param supergroupId Identifier of the supergroup or channel.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public DisableAllSupergroupUsernames(long supergroupId) {
			this.supergroupId = supergroupId;
		}

		/**
		 * Disables all active non-editable usernames of a supergroup or channel, requires owner privileges in the supergroup or channel.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public DisableAllSupergroupUsernames(DataInput input) throws IOException {
			this.supergroupId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return DisableAllSupergroupUsernames.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(DisableAllSupergroupUsernames.CONSTRUCTOR);
			output.writeLong(this.supergroupId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			DisableAllSupergroupUsernames disableAllSupergroupUsernames = (DisableAllSupergroupUsernames) o;
			if (this.supergroupId != disableAllSupergroupUsernames.supergroupId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.supergroupId);
		}
	}

	/**
	 * Disables the currently enabled proxy. Can be called before
	 * authorization.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class DisableProxy extends Function<Ok> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2100095102;

		/**
		 * Disables the currently enabled proxy. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public DisableProxy() {}

		/**
		 * Disables the currently enabled proxy. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/

		/**
		 * Disables the currently enabled proxy. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public DisableProxy(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return DisableProxy.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(DisableProxy.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return DisableProxy.CONSTRUCTOR;
		}
	}

	/**
	 * Discards a call.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class DiscardCall extends Function<Ok> {


		/**
		 * Call identifier.
		**/
		public int callId;

		/**
		 * Pass true if the user was disconnected.
		**/
		public boolean isDisconnected;

		/**
		 * The call duration, in seconds.
		**/
		public int duration;

		/**
		 * Pass true if the call was a video call.
		**/
		public boolean isVideo;

		/**
		 * Identifier of the connection used during the call.
		**/
		public long connectionId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1784044162;

		/**
		 * Discards a call.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public DiscardCall() {}

		/**
		 * Discards a call.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param callId Call identifier.
		 * @param isDisconnected Pass true if the user was disconnected.
		 * @param duration The call duration, in seconds.
		 * @param isVideo Pass true if the call was a video call.
		 * @param connectionId Identifier of the connection used during the call.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public DiscardCall(int callId,
				boolean isDisconnected,
				int duration,
				boolean isVideo,
				long connectionId) {
			this.callId = callId;
			this.isDisconnected = isDisconnected;
			this.duration = duration;
			this.isVideo = isVideo;
			this.connectionId = connectionId;
		}

		/**
		 * Discards a call.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public DiscardCall(DataInput input) throws IOException {
			this.callId = input.readInt();
			this.isDisconnected = input.readBoolean();
			this.duration = input.readInt();
			this.isVideo = input.readBoolean();
			this.connectionId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return DiscardCall.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(DiscardCall.CONSTRUCTOR);
			output.writeInt(this.callId);
			output.writeBoolean(this.isDisconnected);
			output.writeInt(this.duration);
			output.writeBoolean(this.isVideo);
			output.writeLong(this.connectionId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			DiscardCall discardCall = (DiscardCall) o;
			if (this.callId != discardCall.callId) {
				return false;
			}
			if (this.isDisconnected != discardCall.isDisconnected) {
				return false;
			}
			if (this.duration != discardCall.duration) {
				return false;
			}
			if (this.isVideo != discardCall.isVideo) {
				return false;
			}
			if (this.connectionId != discardCall.connectionId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.callId);
			return result;
		}
	}

	/**
	 * Disconnects all websites from the current user&#039;s Telegram
	 * account.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class DisconnectAllWebsites extends Function<Ok> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1082985981;

		/**
		 * Disconnects all websites from the current user&#039;s Telegram account.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public DisconnectAllWebsites() {}

		/**
		 * Disconnects all websites from the current user&#039;s Telegram account.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/

		/**
		 * Disconnects all websites from the current user&#039;s Telegram account.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public DisconnectAllWebsites(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return DisconnectAllWebsites.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(DisconnectAllWebsites.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return DisconnectAllWebsites.CONSTRUCTOR;
		}
	}

	/**
	 * Disconnects website from the current user&#039;s Telegram account.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class DisconnectWebsite extends Function<Ok> {


		/**
		 * Website identifier.
		**/
		public long websiteId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -778767395;

		/**
		 * Disconnects website from the current user&#039;s Telegram account.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public DisconnectWebsite() {}

		/**
		 * Disconnects website from the current user&#039;s Telegram account.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param websiteId Website identifier.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public DisconnectWebsite(long websiteId) {
			this.websiteId = websiteId;
		}

		/**
		 * Disconnects website from the current user&#039;s Telegram account.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public DisconnectWebsite(DataInput input) throws IOException {
			this.websiteId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return DisconnectWebsite.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(DisconnectWebsite.CONSTRUCTOR);
			output.writeLong(this.websiteId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			DisconnectWebsite disconnectWebsite = (DisconnectWebsite) o;
			if (this.websiteId != disconnectWebsite.websiteId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.websiteId);
		}
	}

	/**
	 * Downloads a file from the cloud. Download progress and completion of
	 * the download will be notified through updateFile updates.
	 * <p> Returns {@link File File} </p>
	**/
	public static final class DownloadFile extends Function<File> {


		/**
		 * Identifier of the file to download.
		**/
		public int fileId;

		/**
		 * Priority of the download (1-32). The higher the priority, the earlier the file will be downloaded. If the priorities of two files are equal, then the last one for which downloadFile/addFileToDownloads was called will be downloaded first.
		**/
		public int priority;

		/**
		 * The starting position from which the file needs to be downloaded.
		**/
		public long offset;

		/**
		 * Number of bytes which need to be downloaded starting from the &quot;offset&quot; position before the download will automatically be canceled; use 0 to download without a limit.
		**/
		public long limit;

		/**
		 * Pass true to return response only after the file download has succeeded, has failed, has been canceled, or a new downloadFile request with different offset/limit parameters was sent; pass false to return file state immediately, just after the download has been started.
		**/
		public boolean synchronous;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1059402292;

		/**
		 * Downloads a file from the cloud. Download progress and completion of the download will be notified through updateFile updates.
		 *
		 * <p> Returns {@link File File} </p>
		**/
		public DownloadFile() {}

		/**
		 * Downloads a file from the cloud. Download progress and completion of the download will be notified through updateFile updates.
		 *
		 * <p> Returns {@link File File} </p>
		 *
		 * @param fileId Identifier of the file to download.
		 * @param priority Priority of the download (1-32). The higher the priority, the earlier the file will be downloaded. If the priorities of two files are equal, then the last one for which downloadFile/addFileToDownloads was called will be downloaded first.
		 * @param offset The starting position from which the file needs to be downloaded.
		 * @param limit Number of bytes which need to be downloaded starting from the &quot;offset&quot; position before the download will automatically be canceled; use 0 to download without a limit.
		 * @param synchronous Pass true to return response only after the file download has succeeded, has failed, has been canceled, or a new downloadFile request with different offset/limit parameters was sent; pass false to return file state immediately, just after the download has been started.
		 *
		 * <p> Returns {@link File File} </p>
		**/
		public DownloadFile(int fileId,
				int priority,
				long offset,
				long limit,
				boolean synchronous) {
			this.fileId = fileId;
			this.priority = priority;
			this.offset = offset;
			this.limit = limit;
			this.synchronous = synchronous;
		}

		/**
		 * Downloads a file from the cloud. Download progress and completion of the download will be notified through updateFile updates.
		 *
		 * <p> Returns {@link File File} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public DownloadFile(DataInput input) throws IOException {
			this.fileId = input.readInt();
			this.priority = input.readInt();
			this.offset = input.readLong();
			this.limit = input.readLong();
			this.synchronous = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return DownloadFile.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(DownloadFile.CONSTRUCTOR);
			output.writeInt(this.fileId);
			output.writeInt(this.priority);
			output.writeLong(this.offset);
			output.writeLong(this.limit);
			output.writeBoolean(this.synchronous);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			DownloadFile downloadFile = (DownloadFile) o;
			if (this.fileId != downloadFile.fileId) {
				return false;
			}
			if (this.priority != downloadFile.priority) {
				return false;
			}
			if (this.offset != downloadFile.offset) {
				return false;
			}
			if (this.limit != downloadFile.limit) {
				return false;
			}
			if (this.synchronous != downloadFile.synchronous) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.fileId);
			return result;
		}
	}

	/**
	 * Edits existing chat folder. Returns information about the edited chat
	 * folder.
	 * <p> Returns {@link ChatFolderInfo ChatFolderInfo} </p>
	**/
	public static final class EditChatFolder extends Function<ChatFolderInfo> {


		/**
		 * Chat folder identifier.
		**/
		public int chatFolderId;

		/**
		 * The edited chat folder.
		**/
		public ChatFolder folder;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 53672754;

		/**
		 * Edits existing chat folder. Returns information about the edited chat folder.
		 *
		 * <p> Returns {@link ChatFolderInfo ChatFolderInfo} </p>
		**/
		public EditChatFolder() {}

		/**
		 * Edits existing chat folder. Returns information about the edited chat folder.
		 *
		 * <p> Returns {@link ChatFolderInfo ChatFolderInfo} </p>
		 *
		 * @param chatFolderId Chat folder identifier.
		 * @param folder The edited chat folder.
		 *
		 * <p> Returns {@link ChatFolderInfo ChatFolderInfo} </p>
		**/
		public EditChatFolder(int chatFolderId, ChatFolder folder) {
			this.chatFolderId = chatFolderId;
			this.folder = folder;
		}

		/**
		 * Edits existing chat folder. Returns information about the edited chat folder.
		 *
		 * <p> Returns {@link ChatFolderInfo ChatFolderInfo} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public EditChatFolder(DataInput input) throws IOException {
			this.chatFolderId = input.readInt();
			if (input.readBoolean()) {
				if (ChatFolder.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.folder = new ChatFolder(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return EditChatFolder.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(EditChatFolder.CONSTRUCTOR);
			output.writeInt(this.chatFolderId);
			if (this.folder == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.folder.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			EditChatFolder editChatFolder = (EditChatFolder) o;
			if (this.chatFolderId != editChatFolder.chatFolderId) {
				return false;
			}
			if (!Objects.equals(this.folder, editChatFolder.folder)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.chatFolderId);
			result = result * 31 + (this.folder == null ? 0 : this.folder.hashCode());
			return result;
		}
	}

	/**
	 * Edits an invite link for a chat folder.
	 * <p> Returns {@link ChatFolderInviteLink ChatFolderInviteLink} </p>
	**/
	public static final class EditChatFolderInviteLink extends Function<ChatFolderInviteLink> {


		/**
		 * Chat folder identifier.
		**/
		public int chatFolderId;

		/**
		 * Invite link to be edited.
		**/
		public String inviteLink;

		/**
		 * New name of the link; 0-32 characters.
		**/
		public String name;

		/**
		 * New identifiers of chats to be accessible by the invite link. Use getChatsForChatFolderInviteLink to get suitable chats. Basic groups will be automatically converted to supergroups before link editing.
		**/
		public long[] chatIds;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2141872095;

		/**
		 * Edits an invite link for a chat folder.
		 *
		 * <p> Returns {@link ChatFolderInviteLink ChatFolderInviteLink} </p>
		**/
		public EditChatFolderInviteLink() {}

		/**
		 * Edits an invite link for a chat folder.
		 *
		 * <p> Returns {@link ChatFolderInviteLink ChatFolderInviteLink} </p>
		 *
		 * @param chatFolderId Chat folder identifier.
		 * @param inviteLink Invite link to be edited.
		 * @param name New name of the link; 0-32 characters.
		 * @param chatIds New identifiers of chats to be accessible by the invite link. Use getChatsForChatFolderInviteLink to get suitable chats. Basic groups will be automatically converted to supergroups before link editing.
		 *
		 * <p> Returns {@link ChatFolderInviteLink ChatFolderInviteLink} </p>
		**/
		public EditChatFolderInviteLink(int chatFolderId,
				String inviteLink,
				String name,
				long[] chatIds) {
			this.chatFolderId = chatFolderId;
			this.inviteLink = inviteLink;
			this.name = name;
			this.chatIds = chatIds;
		}

		/**
		 * Edits an invite link for a chat folder.
		 *
		 * <p> Returns {@link ChatFolderInviteLink ChatFolderInviteLink} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public EditChatFolderInviteLink(DataInput input) throws IOException {
			this.chatFolderId = input.readInt();
			if (input.readBoolean()) {
				byte[] inviteLinkTmp = new byte[input.readInt()];
				input.readFully(inviteLinkTmp);
				this.inviteLink = new String(inviteLinkTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] nameTmp = new byte[input.readInt()];
				input.readFully(nameTmp);
				this.name = new String(nameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				this.chatIds = new long[input.readInt()];
				for (int i = 0; i < this.chatIds.length; i++) {
					this.chatIds[i] = input.readLong();
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return EditChatFolderInviteLink.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(EditChatFolderInviteLink.CONSTRUCTOR);
			output.writeInt(this.chatFolderId);
			if (this.inviteLink == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] inviteLinkTmp = this.inviteLink.getBytes(StandardCharsets.UTF_8);
				output.writeInt(inviteLinkTmp.length);
				output.write(inviteLinkTmp);
			}
			if (this.name == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nameTmp = this.name.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nameTmp.length);
				output.write(nameTmp);
			}
			if (this.chatIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.chatIds.length);
				for (int i = 0; i < this.chatIds.length; i++) {
					output.writeLong(this.chatIds[i]);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			EditChatFolderInviteLink editChatFolderInviteLink = (EditChatFolderInviteLink) o;
			if (this.chatFolderId != editChatFolderInviteLink.chatFolderId) {
				return false;
			}
			if (this.inviteLink != editChatFolderInviteLink.inviteLink) {
				return false;
			}
			if (this.name != editChatFolderInviteLink.name) {
				return false;
			}
			if (!Arrays.equals(this.chatIds, editChatFolderInviteLink.chatIds)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.chatFolderId);
			result = result * 31 + (this.inviteLink == null ? 0 : this.inviteLink.hashCode());
			result = result * 31 + (this.name == null ? 0 : this.name.hashCode());
			result = result * 31 + (Arrays.hashCode(this.chatIds));
			return result;
		}
	}

	/**
	 * Edits a non-primary invite link for a chat. Available for basic
	 * groups, supergroups, and channels. Requires administrator privileges
	 * and canInviteUsers right in the chat for own links and owner
	 * privileges for other links.
	 * <p> Returns {@link ChatInviteLink ChatInviteLink} </p>
	**/
	public static final class EditChatInviteLink extends Function<ChatInviteLink> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Invite link to be edited.
		**/
		public String inviteLink;

		/**
		 * Invite link name; 0-32 characters.
		**/
		public String name;

		/**
		 * Point in time (Unix timestamp) when the link will expire; pass 0 if never.
		**/
		public int expirationDate;

		/**
		 * The maximum number of chat members that can join the chat via the link simultaneously; 0-99999; pass 0 if not limited.
		**/
		public int memberLimit;

		/**
		 * Pass true if users joining the chat via the link need to be approved by chat administrators. In this case, memberLimit must be 0.
		**/
		public boolean createsJoinRequest;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1320303996;

		/**
		 * Edits a non-primary invite link for a chat. Available for basic groups, supergroups, and channels. Requires administrator privileges and canInviteUsers right in the chat for own links and owner privileges for other links.
		 *
		 * <p> Returns {@link ChatInviteLink ChatInviteLink} </p>
		**/
		public EditChatInviteLink() {}

		/**
		 * Edits a non-primary invite link for a chat. Available for basic groups, supergroups, and channels. Requires administrator privileges and canInviteUsers right in the chat for own links and owner privileges for other links.
		 *
		 * <p> Returns {@link ChatInviteLink ChatInviteLink} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param inviteLink Invite link to be edited.
		 * @param name Invite link name; 0-32 characters.
		 * @param expirationDate Point in time (Unix timestamp) when the link will expire; pass 0 if never.
		 * @param memberLimit The maximum number of chat members that can join the chat via the link simultaneously; 0-99999; pass 0 if not limited.
		 * @param createsJoinRequest Pass true if users joining the chat via the link need to be approved by chat administrators. In this case, memberLimit must be 0.
		 *
		 * <p> Returns {@link ChatInviteLink ChatInviteLink} </p>
		**/
		public EditChatInviteLink(long chatId,
				String inviteLink,
				String name,
				int expirationDate,
				int memberLimit,
				boolean createsJoinRequest) {
			this.chatId = chatId;
			this.inviteLink = inviteLink;
			this.name = name;
			this.expirationDate = expirationDate;
			this.memberLimit = memberLimit;
			this.createsJoinRequest = createsJoinRequest;
		}

		/**
		 * Edits a non-primary invite link for a chat. Available for basic groups, supergroups, and channels. Requires administrator privileges and canInviteUsers right in the chat for own links and owner privileges for other links.
		 *
		 * <p> Returns {@link ChatInviteLink ChatInviteLink} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public EditChatInviteLink(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				byte[] inviteLinkTmp = new byte[input.readInt()];
				input.readFully(inviteLinkTmp);
				this.inviteLink = new String(inviteLinkTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] nameTmp = new byte[input.readInt()];
				input.readFully(nameTmp);
				this.name = new String(nameTmp, StandardCharsets.UTF_8);
			}
			this.expirationDate = input.readInt();
			this.memberLimit = input.readInt();
			this.createsJoinRequest = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return EditChatInviteLink.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(EditChatInviteLink.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.inviteLink == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] inviteLinkTmp = this.inviteLink.getBytes(StandardCharsets.UTF_8);
				output.writeInt(inviteLinkTmp.length);
				output.write(inviteLinkTmp);
			}
			if (this.name == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nameTmp = this.name.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nameTmp.length);
				output.write(nameTmp);
			}
			output.writeInt(this.expirationDate);
			output.writeInt(this.memberLimit);
			output.writeBoolean(this.createsJoinRequest);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			EditChatInviteLink editChatInviteLink = (EditChatInviteLink) o;
			if (this.chatId != editChatInviteLink.chatId) {
				return false;
			}
			if (this.inviteLink != editChatInviteLink.inviteLink) {
				return false;
			}
			if (this.name != editChatInviteLink.name) {
				return false;
			}
			if (this.expirationDate != editChatInviteLink.expirationDate) {
				return false;
			}
			if (this.memberLimit != editChatInviteLink.memberLimit) {
				return false;
			}
			if (this.createsJoinRequest != editChatInviteLink.createsJoinRequest) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.inviteLink == null ? 0 : this.inviteLink.hashCode());
			result = result * 31 + (this.name == null ? 0 : this.name.hashCode());
			return result;
		}
	}

	/**
	 * Edits information about a custom local language pack in the current
	 * localization target. Can be called before authorization.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class EditCustomLanguagePackInfo extends Function<Ok> {


		/**
		 * New information about the custom local language pack.
		**/
		public LanguagePackInfo info;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1320751257;

		/**
		 * Edits information about a custom local language pack in the current localization target. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public EditCustomLanguagePackInfo() {}

		/**
		 * Edits information about a custom local language pack in the current localization target. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param info New information about the custom local language pack.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public EditCustomLanguagePackInfo(LanguagePackInfo info) {
			this.info = info;
		}

		/**
		 * Edits information about a custom local language pack in the current localization target. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public EditCustomLanguagePackInfo(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (LanguagePackInfo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.info = new LanguagePackInfo(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return EditCustomLanguagePackInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(EditCustomLanguagePackInfo.CONSTRUCTOR);
			if (this.info == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.info.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			EditCustomLanguagePackInfo editCustomLanguagePackInfo = (EditCustomLanguagePackInfo) o;
			if (!Objects.equals(this.info, editCustomLanguagePackInfo.info)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.info == null ? 0 : this.info.hashCode();
		}
	}

	/**
	 * Edits title and icon of a topic in a forum supergroup chat; requires
	 * canManageTopics administrator right in the supergroup unless the user
	 * is creator of the topic.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class EditForumTopic extends Function<Ok> {


		/**
		 * Identifier of the chat.
		**/
		public long chatId;

		/**
		 * Message thread identifier of the forum topic.
		**/
		public long messageThreadId;

		/**
		 * New name of the topic; 0-128 characters. If empty, the previous topic name is kept.
		**/
		public String name;

		/**
		 * Pass true to edit the icon of the topic. Icon of the General topic can&#039;t be edited.
		**/
		public boolean editIconCustomEmoji;

		/**
		 * Identifier of the new custom emoji for topic icon; pass 0 to remove the custom emoji. Ignored if editIconCustomEmoji is false. Telegram Premium users can use any custom emoji, other users can use only a custom emoji returned by getForumTopicDefaultIcons.
		**/
		public long iconCustomEmojiId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1485402016;

		/**
		 * Edits title and icon of a topic in a forum supergroup chat; requires canManageTopics administrator right in the supergroup unless the user is creator of the topic.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public EditForumTopic() {}

		/**
		 * Edits title and icon of a topic in a forum supergroup chat; requires canManageTopics administrator right in the supergroup unless the user is creator of the topic.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Identifier of the chat.
		 * @param messageThreadId Message thread identifier of the forum topic.
		 * @param name New name of the topic; 0-128 characters. If empty, the previous topic name is kept.
		 * @param editIconCustomEmoji Pass true to edit the icon of the topic. Icon of the General topic can&#039;t be edited.
		 * @param iconCustomEmojiId Identifier of the new custom emoji for topic icon; pass 0 to remove the custom emoji. Ignored if editIconCustomEmoji is false. Telegram Premium users can use any custom emoji, other users can use only a custom emoji returned by getForumTopicDefaultIcons.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public EditForumTopic(long chatId,
				long messageThreadId,
				String name,
				boolean editIconCustomEmoji,
				long iconCustomEmojiId) {
			this.chatId = chatId;
			this.messageThreadId = messageThreadId;
			this.name = name;
			this.editIconCustomEmoji = editIconCustomEmoji;
			this.iconCustomEmojiId = iconCustomEmojiId;
		}

		/**
		 * Edits title and icon of a topic in a forum supergroup chat; requires canManageTopics administrator right in the supergroup unless the user is creator of the topic.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public EditForumTopic(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageThreadId = input.readLong();
			if (input.readBoolean()) {
				byte[] nameTmp = new byte[input.readInt()];
				input.readFully(nameTmp);
				this.name = new String(nameTmp, StandardCharsets.UTF_8);
			}
			this.editIconCustomEmoji = input.readBoolean();
			this.iconCustomEmojiId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return EditForumTopic.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(EditForumTopic.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageThreadId);
			if (this.name == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nameTmp = this.name.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nameTmp.length);
				output.write(nameTmp);
			}
			output.writeBoolean(this.editIconCustomEmoji);
			output.writeLong(this.iconCustomEmojiId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			EditForumTopic editForumTopic = (EditForumTopic) o;
			if (this.chatId != editForumTopic.chatId) {
				return false;
			}
			if (this.messageThreadId != editForumTopic.messageThreadId) {
				return false;
			}
			if (this.name != editForumTopic.name) {
				return false;
			}
			if (this.editIconCustomEmoji != editForumTopic.editIconCustomEmoji) {
				return false;
			}
			if (this.iconCustomEmojiId != editForumTopic.iconCustomEmojiId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.name == null ? 0 : this.name.hashCode());
			return result;
		}
	}

	/**
	 * Edits the caption of an inline message sent via a bot; for bots only.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class EditInlineMessageCaption extends Function<Ok> {


		/**
		 * Inline message identifier.
		**/
		public String inlineMessageId;

		/**
		 * The new message reply markup; pass null if none.
		**/
		public ReplyMarkup replyMarkup;

		/**
		 * New message content caption; pass null to remove caption; 0-getOption(&quot;message_caption_length_max&quot;) characters.
		**/
		public FormattedText caption;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -760985929;

		/**
		 * Edits the caption of an inline message sent via a bot; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public EditInlineMessageCaption() {}

		/**
		 * Edits the caption of an inline message sent via a bot; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param inlineMessageId Inline message identifier.
		 * @param replyMarkup The new message reply markup; pass null if none.
		 * @param caption New message content caption; pass null to remove caption; 0-getOption(&quot;message_caption_length_max&quot;) characters.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public EditInlineMessageCaption(String inlineMessageId,
				ReplyMarkup replyMarkup,
				FormattedText caption) {
			this.inlineMessageId = inlineMessageId;
			this.replyMarkup = replyMarkup;
			this.caption = caption;
		}

		/**
		 * Edits the caption of an inline message sent via a bot; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public EditInlineMessageCaption(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] inlineMessageIdTmp = new byte[input.readInt()];
				input.readFully(inlineMessageIdTmp);
				this.inlineMessageId = new String(inlineMessageIdTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ReplyMarkupRemoveKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupRemoveKeyboard(input); break;
					case ReplyMarkupForceReply.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupForceReply(input); break;
					case ReplyMarkupShowKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupShowKeyboard(input); break;
					case ReplyMarkupInlineKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupInlineKeyboard(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				if (FormattedText.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.caption = new FormattedText(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return EditInlineMessageCaption.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(EditInlineMessageCaption.CONSTRUCTOR);
			if (this.inlineMessageId == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] inlineMessageIdTmp = this.inlineMessageId.getBytes(StandardCharsets.UTF_8);
				output.writeInt(inlineMessageIdTmp.length);
				output.write(inlineMessageIdTmp);
			}
			if (this.replyMarkup == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.replyMarkup.serialize(output);
			}
			if (this.caption == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.caption.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			EditInlineMessageCaption editInlineMessageCaption = (EditInlineMessageCaption) o;
			if (this.inlineMessageId != editInlineMessageCaption.inlineMessageId) {
				return false;
			}
			if (!Objects.equals(this.replyMarkup, editInlineMessageCaption.replyMarkup)) {
				return false;
			}
			if (!Objects.equals(this.caption, editInlineMessageCaption.caption)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.inlineMessageId == null ? 0 : this.inlineMessageId.hashCode();
			result = result * 31 + (this.replyMarkup == null ? 0 : this.replyMarkup.hashCode());
			result = result * 31 + (this.caption == null ? 0 : this.caption.hashCode());
			return result;
		}
	}

	/**
	 * Edits the content of a live location in an inline message sent via a
	 * bot; for bots only.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class EditInlineMessageLiveLocation extends Function<Ok> {


		/**
		 * Inline message identifier.
		**/
		public String inlineMessageId;

		/**
		 * The new message reply markup; pass null if none.
		**/
		public ReplyMarkup replyMarkup;

		/**
		 * New location content of the message; pass null to stop sharing the live location.
		**/
		public Location location;

		/**
		 * The new direction in which the location moves, in degrees; 1-360. Pass 0 if unknown.
		**/
		public int heading;

		/**
		 * The new maximum distance for proximity alerts, in meters (0-100000). Pass 0 if the notification is disabled.
		**/
		public int proximityAlertRadius;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -156902912;

		/**
		 * Edits the content of a live location in an inline message sent via a bot; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public EditInlineMessageLiveLocation() {}

		/**
		 * Edits the content of a live location in an inline message sent via a bot; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param inlineMessageId Inline message identifier.
		 * @param replyMarkup The new message reply markup; pass null if none.
		 * @param location New location content of the message; pass null to stop sharing the live location.
		 * @param heading The new direction in which the location moves, in degrees; 1-360. Pass 0 if unknown.
		 * @param proximityAlertRadius The new maximum distance for proximity alerts, in meters (0-100000). Pass 0 if the notification is disabled.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public EditInlineMessageLiveLocation(String inlineMessageId,
				ReplyMarkup replyMarkup,
				Location location,
				int heading,
				int proximityAlertRadius) {
			this.inlineMessageId = inlineMessageId;
			this.replyMarkup = replyMarkup;
			this.location = location;
			this.heading = heading;
			this.proximityAlertRadius = proximityAlertRadius;
		}

		/**
		 * Edits the content of a live location in an inline message sent via a bot; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public EditInlineMessageLiveLocation(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] inlineMessageIdTmp = new byte[input.readInt()];
				input.readFully(inlineMessageIdTmp);
				this.inlineMessageId = new String(inlineMessageIdTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ReplyMarkupRemoveKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupRemoveKeyboard(input); break;
					case ReplyMarkupForceReply.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupForceReply(input); break;
					case ReplyMarkupShowKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupShowKeyboard(input); break;
					case ReplyMarkupInlineKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupInlineKeyboard(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				if (Location.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.location = new Location(input);
			}
			this.heading = input.readInt();
			this.proximityAlertRadius = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return EditInlineMessageLiveLocation.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(EditInlineMessageLiveLocation.CONSTRUCTOR);
			if (this.inlineMessageId == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] inlineMessageIdTmp = this.inlineMessageId.getBytes(StandardCharsets.UTF_8);
				output.writeInt(inlineMessageIdTmp.length);
				output.write(inlineMessageIdTmp);
			}
			if (this.replyMarkup == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.replyMarkup.serialize(output);
			}
			if (this.location == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.location.serialize(output);
			}
			output.writeInt(this.heading);
			output.writeInt(this.proximityAlertRadius);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			EditInlineMessageLiveLocation editInlineMessageLiveLocation = (EditInlineMessageLiveLocation) o;
			if (this.inlineMessageId != editInlineMessageLiveLocation.inlineMessageId) {
				return false;
			}
			if (!Objects.equals(this.replyMarkup, editInlineMessageLiveLocation.replyMarkup)) {
				return false;
			}
			if (!Objects.equals(this.location, editInlineMessageLiveLocation.location)) {
				return false;
			}
			if (this.heading != editInlineMessageLiveLocation.heading) {
				return false;
			}
			if (this.proximityAlertRadius != editInlineMessageLiveLocation.proximityAlertRadius) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.heading);
			result = result * 31 + (this.inlineMessageId == null ? 0 : this.inlineMessageId.hashCode());
			result = result * 31 + (this.replyMarkup == null ? 0 : this.replyMarkup.hashCode());
			result = result * 31 + (this.location == null ? 0 : this.location.hashCode());
			return result;
		}
	}

	/**
	 * Edits the content of a message with an animation, an audio, a
	 * document, a photo or a video in an inline message sent via a bot; for
	 * bots only.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class EditInlineMessageMedia extends Function<Ok> {


		/**
		 * Inline message identifier.
		**/
		public String inlineMessageId;

		/**
		 * The new message reply markup; pass null if none; for bots only.
		**/
		public ReplyMarkup replyMarkup;

		/**
		 * New content of the message. Must be one of the following types: inputMessageAnimation, inputMessageAudio, inputMessageDocument, inputMessagePhoto or inputMessageVideo.
		**/
		public InputMessageContent inputMessageContent;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 23553921;

		/**
		 * Edits the content of a message with an animation, an audio, a document, a photo or a video in an inline message sent via a bot; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public EditInlineMessageMedia() {}

		/**
		 * Edits the content of a message with an animation, an audio, a document, a photo or a video in an inline message sent via a bot; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param inlineMessageId Inline message identifier.
		 * @param replyMarkup The new message reply markup; pass null if none; for bots only.
		 * @param inputMessageContent New content of the message. Must be one of the following types: inputMessageAnimation, inputMessageAudio, inputMessageDocument, inputMessagePhoto or inputMessageVideo.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public EditInlineMessageMedia(String inlineMessageId,
				ReplyMarkup replyMarkup,
				InputMessageContent inputMessageContent) {
			this.inlineMessageId = inlineMessageId;
			this.replyMarkup = replyMarkup;
			this.inputMessageContent = inputMessageContent;
		}

		/**
		 * Edits the content of a message with an animation, an audio, a document, a photo or a video in an inline message sent via a bot; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public EditInlineMessageMedia(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] inlineMessageIdTmp = new byte[input.readInt()];
				input.readFully(inlineMessageIdTmp);
				this.inlineMessageId = new String(inlineMessageIdTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ReplyMarkupRemoveKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupRemoveKeyboard(input); break;
					case ReplyMarkupForceReply.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupForceReply(input); break;
					case ReplyMarkupShowKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupShowKeyboard(input); break;
					case ReplyMarkupInlineKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupInlineKeyboard(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputMessageText.CONSTRUCTOR: this.inputMessageContent = new InputMessageText(input); break;
					case InputMessageAnimation.CONSTRUCTOR: this.inputMessageContent = new InputMessageAnimation(input); break;
					case InputMessageAudio.CONSTRUCTOR: this.inputMessageContent = new InputMessageAudio(input); break;
					case InputMessageDocument.CONSTRUCTOR: this.inputMessageContent = new InputMessageDocument(input); break;
					case InputMessagePhoto.CONSTRUCTOR: this.inputMessageContent = new InputMessagePhoto(input); break;
					case InputMessageSticker.CONSTRUCTOR: this.inputMessageContent = new InputMessageSticker(input); break;
					case InputMessageVideo.CONSTRUCTOR: this.inputMessageContent = new InputMessageVideo(input); break;
					case InputMessageVideoNote.CONSTRUCTOR: this.inputMessageContent = new InputMessageVideoNote(input); break;
					case InputMessageVoiceNote.CONSTRUCTOR: this.inputMessageContent = new InputMessageVoiceNote(input); break;
					case InputMessageLocation.CONSTRUCTOR: this.inputMessageContent = new InputMessageLocation(input); break;
					case InputMessageVenue.CONSTRUCTOR: this.inputMessageContent = new InputMessageVenue(input); break;
					case InputMessageContact.CONSTRUCTOR: this.inputMessageContent = new InputMessageContact(input); break;
					case InputMessageDice.CONSTRUCTOR: this.inputMessageContent = new InputMessageDice(input); break;
					case InputMessageGame.CONSTRUCTOR: this.inputMessageContent = new InputMessageGame(input); break;
					case InputMessageInvoice.CONSTRUCTOR: this.inputMessageContent = new InputMessageInvoice(input); break;
					case InputMessagePoll.CONSTRUCTOR: this.inputMessageContent = new InputMessagePoll(input); break;
					case InputMessageForwarded.CONSTRUCTOR: this.inputMessageContent = new InputMessageForwarded(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return EditInlineMessageMedia.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(EditInlineMessageMedia.CONSTRUCTOR);
			if (this.inlineMessageId == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] inlineMessageIdTmp = this.inlineMessageId.getBytes(StandardCharsets.UTF_8);
				output.writeInt(inlineMessageIdTmp.length);
				output.write(inlineMessageIdTmp);
			}
			if (this.replyMarkup == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.replyMarkup.serialize(output);
			}
			if (this.inputMessageContent == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.inputMessageContent.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			EditInlineMessageMedia editInlineMessageMedia = (EditInlineMessageMedia) o;
			if (this.inlineMessageId != editInlineMessageMedia.inlineMessageId) {
				return false;
			}
			if (!Objects.equals(this.replyMarkup, editInlineMessageMedia.replyMarkup)) {
				return false;
			}
			if (!Objects.equals(this.inputMessageContent, editInlineMessageMedia.inputMessageContent)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.inlineMessageId == null ? 0 : this.inlineMessageId.hashCode();
			result = result * 31 + (this.replyMarkup == null ? 0 : this.replyMarkup.hashCode());
			result = result * 31 + (this.inputMessageContent == null ? 0 : this.inputMessageContent.hashCode());
			return result;
		}
	}

	/**
	 * Edits the reply markup of an inline message sent via a bot; for bots
	 * only.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class EditInlineMessageReplyMarkup extends Function<Ok> {


		/**
		 * Inline message identifier.
		**/
		public String inlineMessageId;

		/**
		 * The new message reply markup; pass null if none.
		**/
		public ReplyMarkup replyMarkup;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -67565858;

		/**
		 * Edits the reply markup of an inline message sent via a bot; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public EditInlineMessageReplyMarkup() {}

		/**
		 * Edits the reply markup of an inline message sent via a bot; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param inlineMessageId Inline message identifier.
		 * @param replyMarkup The new message reply markup; pass null if none.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public EditInlineMessageReplyMarkup(String inlineMessageId, ReplyMarkup replyMarkup) {
			this.inlineMessageId = inlineMessageId;
			this.replyMarkup = replyMarkup;
		}

		/**
		 * Edits the reply markup of an inline message sent via a bot; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public EditInlineMessageReplyMarkup(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] inlineMessageIdTmp = new byte[input.readInt()];
				input.readFully(inlineMessageIdTmp);
				this.inlineMessageId = new String(inlineMessageIdTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ReplyMarkupRemoveKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupRemoveKeyboard(input); break;
					case ReplyMarkupForceReply.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupForceReply(input); break;
					case ReplyMarkupShowKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupShowKeyboard(input); break;
					case ReplyMarkupInlineKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupInlineKeyboard(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return EditInlineMessageReplyMarkup.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(EditInlineMessageReplyMarkup.CONSTRUCTOR);
			if (this.inlineMessageId == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] inlineMessageIdTmp = this.inlineMessageId.getBytes(StandardCharsets.UTF_8);
				output.writeInt(inlineMessageIdTmp.length);
				output.write(inlineMessageIdTmp);
			}
			if (this.replyMarkup == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.replyMarkup.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			EditInlineMessageReplyMarkup editInlineMessageReplyMarkup = (EditInlineMessageReplyMarkup) o;
			if (this.inlineMessageId != editInlineMessageReplyMarkup.inlineMessageId) {
				return false;
			}
			if (!Objects.equals(this.replyMarkup, editInlineMessageReplyMarkup.replyMarkup)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.inlineMessageId == null ? 0 : this.inlineMessageId.hashCode();
			result = result * 31 + (this.replyMarkup == null ? 0 : this.replyMarkup.hashCode());
			return result;
		}
	}

	/**
	 * Edits the text of an inline text or game message sent via a bot; for
	 * bots only.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class EditInlineMessageText extends Function<Ok> {


		/**
		 * Inline message identifier.
		**/
		public String inlineMessageId;

		/**
		 * The new message reply markup; pass null if none.
		**/
		public ReplyMarkup replyMarkup;

		/**
		 * New text content of the message. Must be of type inputMessageText.
		**/
		public InputMessageContent inputMessageContent;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -855457307;

		/**
		 * Edits the text of an inline text or game message sent via a bot; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public EditInlineMessageText() {}

		/**
		 * Edits the text of an inline text or game message sent via a bot; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param inlineMessageId Inline message identifier.
		 * @param replyMarkup The new message reply markup; pass null if none.
		 * @param inputMessageContent New text content of the message. Must be of type inputMessageText.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public EditInlineMessageText(String inlineMessageId,
				ReplyMarkup replyMarkup,
				InputMessageContent inputMessageContent) {
			this.inlineMessageId = inlineMessageId;
			this.replyMarkup = replyMarkup;
			this.inputMessageContent = inputMessageContent;
		}

		/**
		 * Edits the text of an inline text or game message sent via a bot; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public EditInlineMessageText(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] inlineMessageIdTmp = new byte[input.readInt()];
				input.readFully(inlineMessageIdTmp);
				this.inlineMessageId = new String(inlineMessageIdTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ReplyMarkupRemoveKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupRemoveKeyboard(input); break;
					case ReplyMarkupForceReply.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupForceReply(input); break;
					case ReplyMarkupShowKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupShowKeyboard(input); break;
					case ReplyMarkupInlineKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupInlineKeyboard(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputMessageText.CONSTRUCTOR: this.inputMessageContent = new InputMessageText(input); break;
					case InputMessageAnimation.CONSTRUCTOR: this.inputMessageContent = new InputMessageAnimation(input); break;
					case InputMessageAudio.CONSTRUCTOR: this.inputMessageContent = new InputMessageAudio(input); break;
					case InputMessageDocument.CONSTRUCTOR: this.inputMessageContent = new InputMessageDocument(input); break;
					case InputMessagePhoto.CONSTRUCTOR: this.inputMessageContent = new InputMessagePhoto(input); break;
					case InputMessageSticker.CONSTRUCTOR: this.inputMessageContent = new InputMessageSticker(input); break;
					case InputMessageVideo.CONSTRUCTOR: this.inputMessageContent = new InputMessageVideo(input); break;
					case InputMessageVideoNote.CONSTRUCTOR: this.inputMessageContent = new InputMessageVideoNote(input); break;
					case InputMessageVoiceNote.CONSTRUCTOR: this.inputMessageContent = new InputMessageVoiceNote(input); break;
					case InputMessageLocation.CONSTRUCTOR: this.inputMessageContent = new InputMessageLocation(input); break;
					case InputMessageVenue.CONSTRUCTOR: this.inputMessageContent = new InputMessageVenue(input); break;
					case InputMessageContact.CONSTRUCTOR: this.inputMessageContent = new InputMessageContact(input); break;
					case InputMessageDice.CONSTRUCTOR: this.inputMessageContent = new InputMessageDice(input); break;
					case InputMessageGame.CONSTRUCTOR: this.inputMessageContent = new InputMessageGame(input); break;
					case InputMessageInvoice.CONSTRUCTOR: this.inputMessageContent = new InputMessageInvoice(input); break;
					case InputMessagePoll.CONSTRUCTOR: this.inputMessageContent = new InputMessagePoll(input); break;
					case InputMessageForwarded.CONSTRUCTOR: this.inputMessageContent = new InputMessageForwarded(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return EditInlineMessageText.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(EditInlineMessageText.CONSTRUCTOR);
			if (this.inlineMessageId == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] inlineMessageIdTmp = this.inlineMessageId.getBytes(StandardCharsets.UTF_8);
				output.writeInt(inlineMessageIdTmp.length);
				output.write(inlineMessageIdTmp);
			}
			if (this.replyMarkup == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.replyMarkup.serialize(output);
			}
			if (this.inputMessageContent == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.inputMessageContent.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			EditInlineMessageText editInlineMessageText = (EditInlineMessageText) o;
			if (this.inlineMessageId != editInlineMessageText.inlineMessageId) {
				return false;
			}
			if (!Objects.equals(this.replyMarkup, editInlineMessageText.replyMarkup)) {
				return false;
			}
			if (!Objects.equals(this.inputMessageContent, editInlineMessageText.inputMessageContent)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.inlineMessageId == null ? 0 : this.inlineMessageId.hashCode();
			result = result * 31 + (this.replyMarkup == null ? 0 : this.replyMarkup.hashCode());
			result = result * 31 + (this.inputMessageContent == null ? 0 : this.inputMessageContent.hashCode());
			return result;
		}
	}

	/**
	 * Edits the message content caption. Returns the edited message after
	 * the edit is completed on the server side.
	 * <p> Returns {@link Message Message} </p>
	**/
	public static final class EditMessageCaption extends Function<Message> {


		/**
		 * The chat the message belongs to.
		**/
		public long chatId;

		/**
		 * Identifier of the message.
		**/
		public long messageId;

		/**
		 * The new message reply markup; pass null if none; for bots only.
		**/
		public ReplyMarkup replyMarkup;

		/**
		 * New message content caption; 0-getOption(&quot;message_caption_length_max&quot;) characters; pass null to remove caption.
		**/
		public FormattedText caption;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1154677038;

		/**
		 * Edits the message content caption. Returns the edited message after the edit is completed on the server side.
		 *
		 * <p> Returns {@link Message Message} </p>
		**/
		public EditMessageCaption() {}

		/**
		 * Edits the message content caption. Returns the edited message after the edit is completed on the server side.
		 *
		 * <p> Returns {@link Message Message} </p>
		 *
		 * @param chatId The chat the message belongs to.
		 * @param messageId Identifier of the message.
		 * @param replyMarkup The new message reply markup; pass null if none; for bots only.
		 * @param caption New message content caption; 0-getOption(&quot;message_caption_length_max&quot;) characters; pass null to remove caption.
		 *
		 * <p> Returns {@link Message Message} </p>
		**/
		public EditMessageCaption(long chatId,
				long messageId,
				ReplyMarkup replyMarkup,
				FormattedText caption) {
			this.chatId = chatId;
			this.messageId = messageId;
			this.replyMarkup = replyMarkup;
			this.caption = caption;
		}

		/**
		 * Edits the message content caption. Returns the edited message after the edit is completed on the server side.
		 *
		 * <p> Returns {@link Message Message} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public EditMessageCaption(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ReplyMarkupRemoveKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupRemoveKeyboard(input); break;
					case ReplyMarkupForceReply.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupForceReply(input); break;
					case ReplyMarkupShowKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupShowKeyboard(input); break;
					case ReplyMarkupInlineKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupInlineKeyboard(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				if (FormattedText.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.caption = new FormattedText(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return EditMessageCaption.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(EditMessageCaption.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
			if (this.replyMarkup == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.replyMarkup.serialize(output);
			}
			if (this.caption == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.caption.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			EditMessageCaption editMessageCaption = (EditMessageCaption) o;
			if (this.chatId != editMessageCaption.chatId) {
				return false;
			}
			if (this.messageId != editMessageCaption.messageId) {
				return false;
			}
			if (!Objects.equals(this.replyMarkup, editMessageCaption.replyMarkup)) {
				return false;
			}
			if (!Objects.equals(this.caption, editMessageCaption.caption)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.replyMarkup == null ? 0 : this.replyMarkup.hashCode());
			result = result * 31 + (this.caption == null ? 0 : this.caption.hashCode());
			return result;
		}
	}

	/**
	 * Edits the message content of a live location. Messages can be edited
	 * for a limited period of time specified in the live location. Returns
	 * the edited message after the edit is completed on the server side.
	 * <p> Returns {@link Message Message} </p>
	**/
	public static final class EditMessageLiveLocation extends Function<Message> {


		/**
		 * The chat the message belongs to.
		**/
		public long chatId;

		/**
		 * Identifier of the message.
		**/
		public long messageId;

		/**
		 * The new message reply markup; pass null if none; for bots only.
		**/
		public ReplyMarkup replyMarkup;

		/**
		 * New location content of the message; pass null to stop sharing the live location.
		**/
		public Location location;

		/**
		 * The new direction in which the location moves, in degrees; 1-360. Pass 0 if unknown.
		**/
		public int heading;

		/**
		 * The new maximum distance for proximity alerts, in meters (0-100000). Pass 0 if the notification is disabled.
		**/
		public int proximityAlertRadius;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -14047982;

		/**
		 * Edits the message content of a live location. Messages can be edited for a limited period of time specified in the live location. Returns the edited message after the edit is completed on the server side.
		 *
		 * <p> Returns {@link Message Message} </p>
		**/
		public EditMessageLiveLocation() {}

		/**
		 * Edits the message content of a live location. Messages can be edited for a limited period of time specified in the live location. Returns the edited message after the edit is completed on the server side.
		 *
		 * <p> Returns {@link Message Message} </p>
		 *
		 * @param chatId The chat the message belongs to.
		 * @param messageId Identifier of the message.
		 * @param replyMarkup The new message reply markup; pass null if none; for bots only.
		 * @param location New location content of the message; pass null to stop sharing the live location.
		 * @param heading The new direction in which the location moves, in degrees; 1-360. Pass 0 if unknown.
		 * @param proximityAlertRadius The new maximum distance for proximity alerts, in meters (0-100000). Pass 0 if the notification is disabled.
		 *
		 * <p> Returns {@link Message Message} </p>
		**/
		public EditMessageLiveLocation(long chatId,
				long messageId,
				ReplyMarkup replyMarkup,
				Location location,
				int heading,
				int proximityAlertRadius) {
			this.chatId = chatId;
			this.messageId = messageId;
			this.replyMarkup = replyMarkup;
			this.location = location;
			this.heading = heading;
			this.proximityAlertRadius = proximityAlertRadius;
		}

		/**
		 * Edits the message content of a live location. Messages can be edited for a limited period of time specified in the live location. Returns the edited message after the edit is completed on the server side.
		 *
		 * <p> Returns {@link Message Message} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public EditMessageLiveLocation(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ReplyMarkupRemoveKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupRemoveKeyboard(input); break;
					case ReplyMarkupForceReply.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupForceReply(input); break;
					case ReplyMarkupShowKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupShowKeyboard(input); break;
					case ReplyMarkupInlineKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupInlineKeyboard(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				if (Location.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.location = new Location(input);
			}
			this.heading = input.readInt();
			this.proximityAlertRadius = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return EditMessageLiveLocation.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(EditMessageLiveLocation.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
			if (this.replyMarkup == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.replyMarkup.serialize(output);
			}
			if (this.location == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.location.serialize(output);
			}
			output.writeInt(this.heading);
			output.writeInt(this.proximityAlertRadius);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			EditMessageLiveLocation editMessageLiveLocation = (EditMessageLiveLocation) o;
			if (this.chatId != editMessageLiveLocation.chatId) {
				return false;
			}
			if (this.messageId != editMessageLiveLocation.messageId) {
				return false;
			}
			if (!Objects.equals(this.replyMarkup, editMessageLiveLocation.replyMarkup)) {
				return false;
			}
			if (!Objects.equals(this.location, editMessageLiveLocation.location)) {
				return false;
			}
			if (this.heading != editMessageLiveLocation.heading) {
				return false;
			}
			if (this.proximityAlertRadius != editMessageLiveLocation.proximityAlertRadius) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.replyMarkup == null ? 0 : this.replyMarkup.hashCode());
			result = result * 31 + (this.location == null ? 0 : this.location.hashCode());
			return result;
		}
	}

	/**
	 * Edits the content of a message with an animation, an audio, a
	 * document, a photo or a video, including message caption. If only the
	 * caption needs to be edited, use editMessageCaption instead. The media
	 * can&#039;t be edited if the message was set to self-destruct or to a
	 * self-destructing media. The type of message content in an album
	 * can&#039;t be changed with exception of replacing a photo with a
	 * video or vice versa. Returns the edited message after the edit is
	 * completed on the server side.
	 * <p> Returns {@link Message Message} </p>
	**/
	public static final class EditMessageMedia extends Function<Message> {


		/**
		 * The chat the message belongs to.
		**/
		public long chatId;

		/**
		 * Identifier of the message.
		**/
		public long messageId;

		/**
		 * The new message reply markup; pass null if none; for bots only.
		**/
		public ReplyMarkup replyMarkup;

		/**
		 * New content of the message. Must be one of the following types: inputMessageAnimation, inputMessageAudio, inputMessageDocument, inputMessagePhoto or inputMessageVideo.
		**/
		public InputMessageContent inputMessageContent;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1152678125;

		/**
		 * Edits the content of a message with an animation, an audio, a document, a photo or a video, including message caption. If only the caption needs to be edited, use editMessageCaption instead. The media can&#039;t be edited if the message was set to self-destruct or to a self-destructing media. The type of message content in an album can&#039;t be changed with exception of replacing a photo with a video or vice versa. Returns the edited message after the edit is completed on the server side.
		 *
		 * <p> Returns {@link Message Message} </p>
		**/
		public EditMessageMedia() {}

		/**
		 * Edits the content of a message with an animation, an audio, a document, a photo or a video, including message caption. If only the caption needs to be edited, use editMessageCaption instead. The media can&#039;t be edited if the message was set to self-destruct or to a self-destructing media. The type of message content in an album can&#039;t be changed with exception of replacing a photo with a video or vice versa. Returns the edited message after the edit is completed on the server side.
		 *
		 * <p> Returns {@link Message Message} </p>
		 *
		 * @param chatId The chat the message belongs to.
		 * @param messageId Identifier of the message.
		 * @param replyMarkup The new message reply markup; pass null if none; for bots only.
		 * @param inputMessageContent New content of the message. Must be one of the following types: inputMessageAnimation, inputMessageAudio, inputMessageDocument, inputMessagePhoto or inputMessageVideo.
		 *
		 * <p> Returns {@link Message Message} </p>
		**/
		public EditMessageMedia(long chatId,
				long messageId,
				ReplyMarkup replyMarkup,
				InputMessageContent inputMessageContent) {
			this.chatId = chatId;
			this.messageId = messageId;
			this.replyMarkup = replyMarkup;
			this.inputMessageContent = inputMessageContent;
		}

		/**
		 * Edits the content of a message with an animation, an audio, a document, a photo or a video, including message caption. If only the caption needs to be edited, use editMessageCaption instead. The media can&#039;t be edited if the message was set to self-destruct or to a self-destructing media. The type of message content in an album can&#039;t be changed with exception of replacing a photo with a video or vice versa. Returns the edited message after the edit is completed on the server side.
		 *
		 * <p> Returns {@link Message Message} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public EditMessageMedia(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ReplyMarkupRemoveKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupRemoveKeyboard(input); break;
					case ReplyMarkupForceReply.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupForceReply(input); break;
					case ReplyMarkupShowKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupShowKeyboard(input); break;
					case ReplyMarkupInlineKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupInlineKeyboard(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputMessageText.CONSTRUCTOR: this.inputMessageContent = new InputMessageText(input); break;
					case InputMessageAnimation.CONSTRUCTOR: this.inputMessageContent = new InputMessageAnimation(input); break;
					case InputMessageAudio.CONSTRUCTOR: this.inputMessageContent = new InputMessageAudio(input); break;
					case InputMessageDocument.CONSTRUCTOR: this.inputMessageContent = new InputMessageDocument(input); break;
					case InputMessagePhoto.CONSTRUCTOR: this.inputMessageContent = new InputMessagePhoto(input); break;
					case InputMessageSticker.CONSTRUCTOR: this.inputMessageContent = new InputMessageSticker(input); break;
					case InputMessageVideo.CONSTRUCTOR: this.inputMessageContent = new InputMessageVideo(input); break;
					case InputMessageVideoNote.CONSTRUCTOR: this.inputMessageContent = new InputMessageVideoNote(input); break;
					case InputMessageVoiceNote.CONSTRUCTOR: this.inputMessageContent = new InputMessageVoiceNote(input); break;
					case InputMessageLocation.CONSTRUCTOR: this.inputMessageContent = new InputMessageLocation(input); break;
					case InputMessageVenue.CONSTRUCTOR: this.inputMessageContent = new InputMessageVenue(input); break;
					case InputMessageContact.CONSTRUCTOR: this.inputMessageContent = new InputMessageContact(input); break;
					case InputMessageDice.CONSTRUCTOR: this.inputMessageContent = new InputMessageDice(input); break;
					case InputMessageGame.CONSTRUCTOR: this.inputMessageContent = new InputMessageGame(input); break;
					case InputMessageInvoice.CONSTRUCTOR: this.inputMessageContent = new InputMessageInvoice(input); break;
					case InputMessagePoll.CONSTRUCTOR: this.inputMessageContent = new InputMessagePoll(input); break;
					case InputMessageForwarded.CONSTRUCTOR: this.inputMessageContent = new InputMessageForwarded(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return EditMessageMedia.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(EditMessageMedia.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
			if (this.replyMarkup == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.replyMarkup.serialize(output);
			}
			if (this.inputMessageContent == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.inputMessageContent.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			EditMessageMedia editMessageMedia = (EditMessageMedia) o;
			if (this.chatId != editMessageMedia.chatId) {
				return false;
			}
			if (this.messageId != editMessageMedia.messageId) {
				return false;
			}
			if (!Objects.equals(this.replyMarkup, editMessageMedia.replyMarkup)) {
				return false;
			}
			if (!Objects.equals(this.inputMessageContent, editMessageMedia.inputMessageContent)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.replyMarkup == null ? 0 : this.replyMarkup.hashCode());
			result = result * 31 + (this.inputMessageContent == null ? 0 : this.inputMessageContent.hashCode());
			return result;
		}
	}

	/**
	 * Edits the message reply markup; for bots only. Returns the edited
	 * message after the edit is completed on the server side.
	 * <p> Returns {@link Message Message} </p>
	**/
	public static final class EditMessageReplyMarkup extends Function<Message> {


		/**
		 * The chat the message belongs to.
		**/
		public long chatId;

		/**
		 * Identifier of the message.
		**/
		public long messageId;

		/**
		 * The new message reply markup; pass null if none.
		**/
		public ReplyMarkup replyMarkup;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 332127881;

		/**
		 * Edits the message reply markup; for bots only. Returns the edited message after the edit is completed on the server side.
		 *
		 * <p> Returns {@link Message Message} </p>
		**/
		public EditMessageReplyMarkup() {}

		/**
		 * Edits the message reply markup; for bots only. Returns the edited message after the edit is completed on the server side.
		 *
		 * <p> Returns {@link Message Message} </p>
		 *
		 * @param chatId The chat the message belongs to.
		 * @param messageId Identifier of the message.
		 * @param replyMarkup The new message reply markup; pass null if none.
		 *
		 * <p> Returns {@link Message Message} </p>
		**/
		public EditMessageReplyMarkup(long chatId, long messageId, ReplyMarkup replyMarkup) {
			this.chatId = chatId;
			this.messageId = messageId;
			this.replyMarkup = replyMarkup;
		}

		/**
		 * Edits the message reply markup; for bots only. Returns the edited message after the edit is completed on the server side.
		 *
		 * <p> Returns {@link Message Message} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public EditMessageReplyMarkup(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ReplyMarkupRemoveKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupRemoveKeyboard(input); break;
					case ReplyMarkupForceReply.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupForceReply(input); break;
					case ReplyMarkupShowKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupShowKeyboard(input); break;
					case ReplyMarkupInlineKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupInlineKeyboard(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return EditMessageReplyMarkup.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(EditMessageReplyMarkup.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
			if (this.replyMarkup == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.replyMarkup.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			EditMessageReplyMarkup editMessageReplyMarkup = (EditMessageReplyMarkup) o;
			if (this.chatId != editMessageReplyMarkup.chatId) {
				return false;
			}
			if (this.messageId != editMessageReplyMarkup.messageId) {
				return false;
			}
			if (!Objects.equals(this.replyMarkup, editMessageReplyMarkup.replyMarkup)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.replyMarkup == null ? 0 : this.replyMarkup.hashCode());
			return result;
		}
	}

	/**
	 * Edits the time when a scheduled message will be sent. Scheduling
	 * state of all messages in the same album or forwarded together with
	 * the message will be also changed.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class EditMessageSchedulingState extends Function<Ok> {


		/**
		 * The chat the message belongs to.
		**/
		public long chatId;

		/**
		 * Identifier of the message.
		**/
		public long messageId;

		/**
		 * The new message scheduling state; pass null to send the message immediately.
		**/
		public MessageSchedulingState schedulingState;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1372976192;

		/**
		 * Edits the time when a scheduled message will be sent. Scheduling state of all messages in the same album or forwarded together with the message will be also changed.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public EditMessageSchedulingState() {}

		/**
		 * Edits the time when a scheduled message will be sent. Scheduling state of all messages in the same album or forwarded together with the message will be also changed.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId The chat the message belongs to.
		 * @param messageId Identifier of the message.
		 * @param schedulingState The new message scheduling state; pass null to send the message immediately.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public EditMessageSchedulingState(long chatId,
				long messageId,
				MessageSchedulingState schedulingState) {
			this.chatId = chatId;
			this.messageId = messageId;
			this.schedulingState = schedulingState;
		}

		/**
		 * Edits the time when a scheduled message will be sent. Scheduling state of all messages in the same album or forwarded together with the message will be also changed.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public EditMessageSchedulingState(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case MessageSchedulingStateSendAtDate.CONSTRUCTOR: this.schedulingState = new MessageSchedulingStateSendAtDate(input); break;
					case MessageSchedulingStateSendWhenOnline.CONSTRUCTOR: this.schedulingState = new MessageSchedulingStateSendWhenOnline(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return EditMessageSchedulingState.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(EditMessageSchedulingState.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
			if (this.schedulingState == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.schedulingState.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			EditMessageSchedulingState editMessageSchedulingState = (EditMessageSchedulingState) o;
			if (this.chatId != editMessageSchedulingState.chatId) {
				return false;
			}
			if (this.messageId != editMessageSchedulingState.messageId) {
				return false;
			}
			if (!Objects.equals(this.schedulingState, editMessageSchedulingState.schedulingState)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.schedulingState == null ? 0 : this.schedulingState.hashCode());
			return result;
		}
	}

	/**
	 * Edits the text of a message (or a text of a game message). Returns
	 * the edited message after the edit is completed on the server side.
	 * <p> Returns {@link Message Message} </p>
	**/
	public static final class EditMessageText extends Function<Message> {


		/**
		 * The chat the message belongs to.
		**/
		public long chatId;

		/**
		 * Identifier of the message.
		**/
		public long messageId;

		/**
		 * The new message reply markup; pass null if none; for bots only.
		**/
		public ReplyMarkup replyMarkup;

		/**
		 * New text content of the message. Must be of type inputMessageText.
		**/
		public InputMessageContent inputMessageContent;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 196272567;

		/**
		 * Edits the text of a message (or a text of a game message). Returns the edited message after the edit is completed on the server side.
		 *
		 * <p> Returns {@link Message Message} </p>
		**/
		public EditMessageText() {}

		/**
		 * Edits the text of a message (or a text of a game message). Returns the edited message after the edit is completed on the server side.
		 *
		 * <p> Returns {@link Message Message} </p>
		 *
		 * @param chatId The chat the message belongs to.
		 * @param messageId Identifier of the message.
		 * @param replyMarkup The new message reply markup; pass null if none; for bots only.
		 * @param inputMessageContent New text content of the message. Must be of type inputMessageText.
		 *
		 * <p> Returns {@link Message Message} </p>
		**/
		public EditMessageText(long chatId,
				long messageId,
				ReplyMarkup replyMarkup,
				InputMessageContent inputMessageContent) {
			this.chatId = chatId;
			this.messageId = messageId;
			this.replyMarkup = replyMarkup;
			this.inputMessageContent = inputMessageContent;
		}

		/**
		 * Edits the text of a message (or a text of a game message). Returns the edited message after the edit is completed on the server side.
		 *
		 * <p> Returns {@link Message Message} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public EditMessageText(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ReplyMarkupRemoveKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupRemoveKeyboard(input); break;
					case ReplyMarkupForceReply.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupForceReply(input); break;
					case ReplyMarkupShowKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupShowKeyboard(input); break;
					case ReplyMarkupInlineKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupInlineKeyboard(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputMessageText.CONSTRUCTOR: this.inputMessageContent = new InputMessageText(input); break;
					case InputMessageAnimation.CONSTRUCTOR: this.inputMessageContent = new InputMessageAnimation(input); break;
					case InputMessageAudio.CONSTRUCTOR: this.inputMessageContent = new InputMessageAudio(input); break;
					case InputMessageDocument.CONSTRUCTOR: this.inputMessageContent = new InputMessageDocument(input); break;
					case InputMessagePhoto.CONSTRUCTOR: this.inputMessageContent = new InputMessagePhoto(input); break;
					case InputMessageSticker.CONSTRUCTOR: this.inputMessageContent = new InputMessageSticker(input); break;
					case InputMessageVideo.CONSTRUCTOR: this.inputMessageContent = new InputMessageVideo(input); break;
					case InputMessageVideoNote.CONSTRUCTOR: this.inputMessageContent = new InputMessageVideoNote(input); break;
					case InputMessageVoiceNote.CONSTRUCTOR: this.inputMessageContent = new InputMessageVoiceNote(input); break;
					case InputMessageLocation.CONSTRUCTOR: this.inputMessageContent = new InputMessageLocation(input); break;
					case InputMessageVenue.CONSTRUCTOR: this.inputMessageContent = new InputMessageVenue(input); break;
					case InputMessageContact.CONSTRUCTOR: this.inputMessageContent = new InputMessageContact(input); break;
					case InputMessageDice.CONSTRUCTOR: this.inputMessageContent = new InputMessageDice(input); break;
					case InputMessageGame.CONSTRUCTOR: this.inputMessageContent = new InputMessageGame(input); break;
					case InputMessageInvoice.CONSTRUCTOR: this.inputMessageContent = new InputMessageInvoice(input); break;
					case InputMessagePoll.CONSTRUCTOR: this.inputMessageContent = new InputMessagePoll(input); break;
					case InputMessageForwarded.CONSTRUCTOR: this.inputMessageContent = new InputMessageForwarded(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return EditMessageText.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(EditMessageText.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
			if (this.replyMarkup == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.replyMarkup.serialize(output);
			}
			if (this.inputMessageContent == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.inputMessageContent.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			EditMessageText editMessageText = (EditMessageText) o;
			if (this.chatId != editMessageText.chatId) {
				return false;
			}
			if (this.messageId != editMessageText.messageId) {
				return false;
			}
			if (!Objects.equals(this.replyMarkup, editMessageText.replyMarkup)) {
				return false;
			}
			if (!Objects.equals(this.inputMessageContent, editMessageText.inputMessageContent)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.replyMarkup == null ? 0 : this.replyMarkup.hashCode());
			result = result * 31 + (this.inputMessageContent == null ? 0 : this.inputMessageContent.hashCode());
			return result;
		}
	}

	/**
	 * Edits an existing proxy server for network requests. Can be called
	 * before authorization.
	 * <p> Returns {@link Proxy Proxy} </p>
	**/
	public static final class EditProxy extends Function<Proxy> {


		/**
		 * Proxy identifier.
		**/
		public int proxyId;

		/**
		 * Proxy server IP address.
		**/
		public String server;

		/**
		 * Proxy server port.
		**/
		public int port;

		/**
		 * Pass true to immediately enable the proxy.
		**/
		public boolean enable;

		/**
		 * Proxy type.
		**/
		public ProxyType type;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1605883821;

		/**
		 * Edits an existing proxy server for network requests. Can be called before authorization.
		 *
		 * <p> Returns {@link Proxy Proxy} </p>
		**/
		public EditProxy() {}

		/**
		 * Edits an existing proxy server for network requests. Can be called before authorization.
		 *
		 * <p> Returns {@link Proxy Proxy} </p>
		 *
		 * @param proxyId Proxy identifier.
		 * @param server Proxy server IP address.
		 * @param port Proxy server port.
		 * @param enable Pass true to immediately enable the proxy.
		 * @param type Proxy type.
		 *
		 * <p> Returns {@link Proxy Proxy} </p>
		**/
		public EditProxy(int proxyId,
				String server,
				int port,
				boolean enable,
				ProxyType type) {
			this.proxyId = proxyId;
			this.server = server;
			this.port = port;
			this.enable = enable;
			this.type = type;
		}

		/**
		 * Edits an existing proxy server for network requests. Can be called before authorization.
		 *
		 * <p> Returns {@link Proxy Proxy} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public EditProxy(DataInput input) throws IOException {
			this.proxyId = input.readInt();
			if (input.readBoolean()) {
				byte[] serverTmp = new byte[input.readInt()];
				input.readFully(serverTmp);
				this.server = new String(serverTmp, StandardCharsets.UTF_8);
			}
			this.port = input.readInt();
			this.enable = input.readBoolean();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ProxyTypeSocks5.CONSTRUCTOR: this.type = new ProxyTypeSocks5(input); break;
					case ProxyTypeHttp.CONSTRUCTOR: this.type = new ProxyTypeHttp(input); break;
					case ProxyTypeMtproto.CONSTRUCTOR: this.type = new ProxyTypeMtproto(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return EditProxy.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(EditProxy.CONSTRUCTOR);
			output.writeInt(this.proxyId);
			if (this.server == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] serverTmp = this.server.getBytes(StandardCharsets.UTF_8);
				output.writeInt(serverTmp.length);
				output.write(serverTmp);
			}
			output.writeInt(this.port);
			output.writeBoolean(this.enable);
			if (this.type == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.type.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			EditProxy editProxy = (EditProxy) o;
			if (this.proxyId != editProxy.proxyId) {
				return false;
			}
			if (this.server != editProxy.server) {
				return false;
			}
			if (this.port != editProxy.port) {
				return false;
			}
			if (this.enable != editProxy.enable) {
				return false;
			}
			if (!Objects.equals(this.type, editProxy.type)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.proxyId);
			result = result * 31 + (this.server == null ? 0 : this.server.hashCode());
			result = result * 31 + (this.type == null ? 0 : this.type.hashCode());
			return result;
		}
	}

	/**
	 * Enables a proxy. Only one proxy can be enabled at a time. Can be
	 * called before authorization.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class EnableProxy extends Function<Ok> {


		/**
		 * Proxy identifier.
		**/
		public int proxyId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1494450838;

		/**
		 * Enables a proxy. Only one proxy can be enabled at a time. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public EnableProxy() {}

		/**
		 * Enables a proxy. Only one proxy can be enabled at a time. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param proxyId Proxy identifier.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public EnableProxy(int proxyId) {
			this.proxyId = proxyId;
		}

		/**
		 * Enables a proxy. Only one proxy can be enabled at a time. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public EnableProxy(DataInput input) throws IOException {
			this.proxyId = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return EnableProxy.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(EnableProxy.CONSTRUCTOR);
			output.writeInt(this.proxyId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			EnableProxy enableProxy = (EnableProxy) o;
			if (this.proxyId != enableProxy.proxyId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.proxyId);
		}
	}

	/**
	 * Ends a group call. Requires groupCall.canBeManaged.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class EndGroupCall extends Function<Ok> {


		/**
		 * Group call identifier.
		**/
		public int groupCallId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 573131959;

		/**
		 * Ends a group call. Requires groupCall.canBeManaged.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public EndGroupCall() {}

		/**
		 * Ends a group call. Requires groupCall.canBeManaged.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param groupCallId Group call identifier.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public EndGroupCall(int groupCallId) {
			this.groupCallId = groupCallId;
		}

		/**
		 * Ends a group call. Requires groupCall.canBeManaged.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public EndGroupCall(DataInput input) throws IOException {
			this.groupCallId = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return EndGroupCall.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(EndGroupCall.CONSTRUCTOR);
			output.writeInt(this.groupCallId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			EndGroupCall endGroupCall = (EndGroupCall) o;
			if (this.groupCallId != endGroupCall.groupCallId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.groupCallId);
		}
	}

	/**
	 * Ends recording of an active group call. Requires
	 * groupCall.canBeManaged group call flag.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class EndGroupCallRecording extends Function<Ok> {


		/**
		 * Group call identifier.
		**/
		public int groupCallId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -75799927;

		/**
		 * Ends recording of an active group call. Requires groupCall.canBeManaged group call flag.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public EndGroupCallRecording() {}

		/**
		 * Ends recording of an active group call. Requires groupCall.canBeManaged group call flag.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param groupCallId Group call identifier.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public EndGroupCallRecording(int groupCallId) {
			this.groupCallId = groupCallId;
		}

		/**
		 * Ends recording of an active group call. Requires groupCall.canBeManaged group call flag.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public EndGroupCallRecording(DataInput input) throws IOException {
			this.groupCallId = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return EndGroupCallRecording.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(EndGroupCallRecording.CONSTRUCTOR);
			output.writeInt(this.groupCallId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			EndGroupCallRecording endGroupCallRecording = (EndGroupCallRecording) o;
			if (this.groupCallId != endGroupCallRecording.groupCallId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.groupCallId);
		}
	}

	/**
	 * Ends screen sharing in a joined group call.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class EndGroupCallScreenSharing extends Function<Ok> {


		/**
		 * Group call identifier.
		**/
		public int groupCallId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2047599540;

		/**
		 * Ends screen sharing in a joined group call.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public EndGroupCallScreenSharing() {}

		/**
		 * Ends screen sharing in a joined group call.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param groupCallId Group call identifier.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public EndGroupCallScreenSharing(int groupCallId) {
			this.groupCallId = groupCallId;
		}

		/**
		 * Ends screen sharing in a joined group call.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public EndGroupCallScreenSharing(DataInput input) throws IOException {
			this.groupCallId = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return EndGroupCallScreenSharing.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(EndGroupCallScreenSharing.CONSTRUCTOR);
			output.writeInt(this.groupCallId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			EndGroupCallScreenSharing endGroupCallScreenSharing = (EndGroupCallScreenSharing) o;
			if (this.groupCallId != endGroupCallScreenSharing.groupCallId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.groupCallId);
		}
	}

	/**
	 * Finishes the file generation.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class FinishFileGeneration extends Function<Ok> {


		/**
		 * The identifier of the generation process.
		**/
		public long generationId;

		/**
		 * If passed, the file generation has failed and must be terminated; pass null if the file generation succeeded.
		**/
		public Error error;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1055060835;

		/**
		 * Finishes the file generation.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public FinishFileGeneration() {}

		/**
		 * Finishes the file generation.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param generationId The identifier of the generation process.
		 * @param error If passed, the file generation has failed and must be terminated; pass null if the file generation succeeded.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public FinishFileGeneration(long generationId, Error error) {
			this.generationId = generationId;
			this.error = error;
		}

		/**
		 * Finishes the file generation.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public FinishFileGeneration(DataInput input) throws IOException {
			this.generationId = input.readLong();
			if (input.readBoolean()) {
				if (Error.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.error = new Error(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return FinishFileGeneration.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(FinishFileGeneration.CONSTRUCTOR);
			output.writeLong(this.generationId);
			if (this.error == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.error.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			FinishFileGeneration finishFileGeneration = (FinishFileGeneration) o;
			if (this.generationId != finishFileGeneration.generationId) {
				return false;
			}
			if (!Objects.equals(this.error, finishFileGeneration.error)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.generationId);
			result = result * 31 + (this.error == null ? 0 : this.error.hashCode());
			return result;
		}
	}

	/**
	 * Forwards previously sent messages. Returns the forwarded messages in
	 * the same order as the message identifiers passed in messageIds. If a
	 * message can&#039;t be forwarded, null will be returned instead of the
	 * message.
	 * <p> Returns {@link Messages Messages} </p>
	**/
	public static final class ForwardMessages extends Function<Messages> {


		/**
		 * Identifier of the chat to which to forward messages.
		**/
		public long chatId;

		/**
		 * If not 0, a message thread identifier in which the message will be sent; for forum threads only.
		**/
		public long messageThreadId;

		/**
		 * Identifier of the chat from which to forward messages.
		**/
		public long fromChatId;

		/**
		 * Identifiers of the messages to forward. Message identifiers must be in a strictly increasing order. At most 100 messages can be forwarded simultaneously.
		**/
		public long[] messageIds;

		/**
		 * Options to be used to send the messages; pass null to use default options.
		**/
		public MessageSendOptions options;

		/**
		 * Pass true to copy content of the messages without reference to the original sender. Always true if the messages are forwarded to a secret chat or are local.
		**/
		public boolean sendCopy;

		/**
		 * Pass true to remove media captions of message copies. Ignored if sendCopy is false.
		**/
		public boolean removeCaption;

		/**
		 * Pass true to get fake messages instead of actually forwarding them.
		**/
		public boolean onlyPreview;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1054441908;

		/**
		 * Forwards previously sent messages. Returns the forwarded messages in the same order as the message identifiers passed in messageIds. If a message can&#039;t be forwarded, null will be returned instead of the message.
		 *
		 * <p> Returns {@link Messages Messages} </p>
		**/
		public ForwardMessages() {}

		/**
		 * Forwards previously sent messages. Returns the forwarded messages in the same order as the message identifiers passed in messageIds. If a message can&#039;t be forwarded, null will be returned instead of the message.
		 *
		 * <p> Returns {@link Messages Messages} </p>
		 *
		 * @param chatId Identifier of the chat to which to forward messages.
		 * @param messageThreadId If not 0, a message thread identifier in which the message will be sent; for forum threads only.
		 * @param fromChatId Identifier of the chat from which to forward messages.
		 * @param messageIds Identifiers of the messages to forward. Message identifiers must be in a strictly increasing order. At most 100 messages can be forwarded simultaneously.
		 * @param options Options to be used to send the messages; pass null to use default options.
		 * @param sendCopy Pass true to copy content of the messages without reference to the original sender. Always true if the messages are forwarded to a secret chat or are local.
		 * @param removeCaption Pass true to remove media captions of message copies. Ignored if sendCopy is false.
		 * @param onlyPreview Pass true to get fake messages instead of actually forwarding them.
		 *
		 * <p> Returns {@link Messages Messages} </p>
		**/
		public ForwardMessages(long chatId,
				long messageThreadId,
				long fromChatId,
				long[] messageIds,
				MessageSendOptions options,
				boolean sendCopy,
				boolean removeCaption,
				boolean onlyPreview) {
			this.chatId = chatId;
			this.messageThreadId = messageThreadId;
			this.fromChatId = fromChatId;
			this.messageIds = messageIds;
			this.options = options;
			this.sendCopy = sendCopy;
			this.removeCaption = removeCaption;
			this.onlyPreview = onlyPreview;
		}

		/**
		 * Forwards previously sent messages. Returns the forwarded messages in the same order as the message identifiers passed in messageIds. If a message can&#039;t be forwarded, null will be returned instead of the message.
		 *
		 * <p> Returns {@link Messages Messages} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ForwardMessages(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageThreadId = input.readLong();
			this.fromChatId = input.readLong();
			if (input.readBoolean()) {
				this.messageIds = new long[input.readInt()];
				for (int i = 0; i < this.messageIds.length; i++) {
					this.messageIds[i] = input.readLong();
				}
			}
			if (input.readBoolean()) {
				if (MessageSendOptions.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.options = new MessageSendOptions(input);
			}
			this.sendCopy = input.readBoolean();
			this.removeCaption = input.readBoolean();
			this.onlyPreview = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ForwardMessages.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ForwardMessages.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageThreadId);
			output.writeLong(this.fromChatId);
			if (this.messageIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.messageIds.length);
				for (int i = 0; i < this.messageIds.length; i++) {
					output.writeLong(this.messageIds[i]);
				}
			}
			if (this.options == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.options.serialize(output);
			}
			output.writeBoolean(this.sendCopy);
			output.writeBoolean(this.removeCaption);
			output.writeBoolean(this.onlyPreview);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ForwardMessages forwardMessages = (ForwardMessages) o;
			if (this.chatId != forwardMessages.chatId) {
				return false;
			}
			if (this.messageThreadId != forwardMessages.messageThreadId) {
				return false;
			}
			if (this.fromChatId != forwardMessages.fromChatId) {
				return false;
			}
			if (!Arrays.equals(this.messageIds, forwardMessages.messageIds)) {
				return false;
			}
			if (!Objects.equals(this.options, forwardMessages.options)) {
				return false;
			}
			if (this.sendCopy != forwardMessages.sendCopy) {
				return false;
			}
			if (this.removeCaption != forwardMessages.removeCaption) {
				return false;
			}
			if (this.onlyPreview != forwardMessages.onlyPreview) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (Arrays.hashCode(this.messageIds));
			result = result * 31 + (this.options == null ? 0 : this.options.hashCode());
			return result;
		}
	}

	/**
	 * Returns the period of inactivity after which the account of the
	 * current user will automatically be deleted.
	 * <p> Returns {@link AccountTtl AccountTtl} </p>
	**/
	public static final class GetAccountTtl extends Function<AccountTtl> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -443905161;

		/**
		 * Returns the period of inactivity after which the account of the current user will automatically be deleted.
		 *
		 * <p> Returns {@link AccountTtl AccountTtl} </p>
		**/
		public GetAccountTtl() {}

		/**
		 * Returns the period of inactivity after which the account of the current user will automatically be deleted.
		 *
		 * <p> Returns {@link AccountTtl AccountTtl} </p>
		 *
		 *
		 * <p> Returns {@link AccountTtl AccountTtl} </p>
		**/

		/**
		 * Returns the period of inactivity after which the account of the current user will automatically be deleted.
		 *
		 * <p> Returns {@link AccountTtl AccountTtl} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetAccountTtl(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetAccountTtl.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetAccountTtl.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return GetAccountTtl.CONSTRUCTOR;
		}
	}

	/**
	 * Returns all active live locations that need to be updated by the
	 * application. The list is persistent across application restarts only
	 * if the message database is used.
	 * <p> Returns {@link Messages Messages} </p>
	**/
	public static final class GetActiveLiveLocationMessages extends Function<Messages> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1425459567;

		/**
		 * Returns all active live locations that need to be updated by the application. The list is persistent across application restarts only if the message database is used.
		 *
		 * <p> Returns {@link Messages Messages} </p>
		**/
		public GetActiveLiveLocationMessages() {}

		/**
		 * Returns all active live locations that need to be updated by the application. The list is persistent across application restarts only if the message database is used.
		 *
		 * <p> Returns {@link Messages Messages} </p>
		 *
		 *
		 * <p> Returns {@link Messages Messages} </p>
		**/

		/**
		 * Returns all active live locations that need to be updated by the application. The list is persistent across application restarts only if the message database is used.
		 *
		 * <p> Returns {@link Messages Messages} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetActiveLiveLocationMessages(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetActiveLiveLocationMessages.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetActiveLiveLocationMessages.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return GetActiveLiveLocationMessages.CONSTRUCTOR;
		}
	}

	/**
	 * Returns all active sessions of the current user.
	 * <p> Returns {@link Sessions Sessions} </p>
	**/
	public static final class GetActiveSessions extends Function<Sessions> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1119710526;

		/**
		 * Returns all active sessions of the current user.
		 *
		 * <p> Returns {@link Sessions Sessions} </p>
		**/
		public GetActiveSessions() {}

		/**
		 * Returns all active sessions of the current user.
		 *
		 * <p> Returns {@link Sessions Sessions} </p>
		 *
		 *
		 * <p> Returns {@link Sessions Sessions} </p>
		**/

		/**
		 * Returns all active sessions of the current user.
		 *
		 * <p> Returns {@link Sessions Sessions} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetActiveSessions(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetActiveSessions.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetActiveSessions.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return GetActiveSessions.CONSTRUCTOR;
		}
	}

	/**
	 * Returns all available Telegram Passport elements.
	 * <p> Returns {@link PassportElements PassportElements} </p>
	**/
	public static final class GetAllPassportElements extends Function<PassportElements> {


		/**
		 * The 2-step verification password of the current user.
		**/
		public String password;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2038945045;

		/**
		 * Returns all available Telegram Passport elements.
		 *
		 * <p> Returns {@link PassportElements PassportElements} </p>
		**/
		public GetAllPassportElements() {}

		/**
		 * Returns all available Telegram Passport elements.
		 *
		 * <p> Returns {@link PassportElements PassportElements} </p>
		 *
		 * @param password The 2-step verification password of the current user.
		 *
		 * <p> Returns {@link PassportElements PassportElements} </p>
		**/
		public GetAllPassportElements(String password) {
			this.password = password;
		}

		/**
		 * Returns all available Telegram Passport elements.
		 *
		 * <p> Returns {@link PassportElements PassportElements} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetAllPassportElements(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] passwordTmp = new byte[input.readInt()];
				input.readFully(passwordTmp);
				this.password = new String(passwordTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetAllPassportElements.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetAllPassportElements.CONSTRUCTOR);
			if (this.password == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] passwordTmp = this.password.getBytes(StandardCharsets.UTF_8);
				output.writeInt(passwordTmp.length);
				output.write(passwordTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetAllPassportElements getAllPassportElements = (GetAllPassportElements) o;
			if (this.password != getAllPassportElements.password) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.password == null ? 0 : this.password.hashCode();
		}
	}

	/**
	 * Returns an animated emoji corresponding to a given emoji. Returns a
	 * 404 error if the emoji has no animated emoji.
	 * <p> Returns {@link AnimatedEmoji AnimatedEmoji} </p>
	**/
	public static final class GetAnimatedEmoji extends Function<AnimatedEmoji> {


		/**
		 * The emoji.
		**/
		public String emoji;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1065635702;

		/**
		 * Returns an animated emoji corresponding to a given emoji. Returns a 404 error if the emoji has no animated emoji.
		 *
		 * <p> Returns {@link AnimatedEmoji AnimatedEmoji} </p>
		**/
		public GetAnimatedEmoji() {}

		/**
		 * Returns an animated emoji corresponding to a given emoji. Returns a 404 error if the emoji has no animated emoji.
		 *
		 * <p> Returns {@link AnimatedEmoji AnimatedEmoji} </p>
		 *
		 * @param emoji The emoji.
		 *
		 * <p> Returns {@link AnimatedEmoji AnimatedEmoji} </p>
		**/
		public GetAnimatedEmoji(String emoji) {
			this.emoji = emoji;
		}

		/**
		 * Returns an animated emoji corresponding to a given emoji. Returns a 404 error if the emoji has no animated emoji.
		 *
		 * <p> Returns {@link AnimatedEmoji AnimatedEmoji} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetAnimatedEmoji(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] emojiTmp = new byte[input.readInt()];
				input.readFully(emojiTmp);
				this.emoji = new String(emojiTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetAnimatedEmoji.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetAnimatedEmoji.CONSTRUCTOR);
			if (this.emoji == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] emojiTmp = this.emoji.getBytes(StandardCharsets.UTF_8);
				output.writeInt(emojiTmp.length);
				output.write(emojiTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetAnimatedEmoji getAnimatedEmoji = (GetAnimatedEmoji) o;
			if (this.emoji != getAnimatedEmoji.emoji) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.emoji == null ? 0 : this.emoji.hashCode();
		}
	}

	/**
	 * Returns application config, provided by the server. Can be called
	 * before authorization.
	 * <p> Returns {@link JsonValue JsonValue} </p>
	**/
	public static final class GetApplicationConfig extends Function<JsonValue> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1823144318;

		/**
		 * Returns application config, provided by the server. Can be called before authorization.
		 *
		 * <p> Returns {@link JsonValue JsonValue} </p>
		**/
		public GetApplicationConfig() {}

		/**
		 * Returns application config, provided by the server. Can be called before authorization.
		 *
		 * <p> Returns {@link JsonValue JsonValue} </p>
		 *
		 *
		 * <p> Returns {@link JsonValue JsonValue} </p>
		**/

		/**
		 * Returns application config, provided by the server. Can be called before authorization.
		 *
		 * <p> Returns {@link JsonValue JsonValue} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetApplicationConfig(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetApplicationConfig.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetApplicationConfig.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return GetApplicationConfig.CONSTRUCTOR;
		}
	}

	/**
	 * Returns the link for downloading official Telegram application to be
	 * used when the current user invites friends to Telegram.
	 * <p> Returns {@link HttpUrl HttpUrl} </p>
	**/
	public static final class GetApplicationDownloadLink extends Function<HttpUrl> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 112013252;

		/**
		 * Returns the link for downloading official Telegram application to be used when the current user invites friends to Telegram.
		 *
		 * <p> Returns {@link HttpUrl HttpUrl} </p>
		**/
		public GetApplicationDownloadLink() {}

		/**
		 * Returns the link for downloading official Telegram application to be used when the current user invites friends to Telegram.
		 *
		 * <p> Returns {@link HttpUrl HttpUrl} </p>
		 *
		 *
		 * <p> Returns {@link HttpUrl HttpUrl} </p>
		**/

		/**
		 * Returns the link for downloading official Telegram application to be used when the current user invites friends to Telegram.
		 *
		 * <p> Returns {@link HttpUrl HttpUrl} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetApplicationDownloadLink(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetApplicationDownloadLink.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetApplicationDownloadLink.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return GetApplicationDownloadLink.CONSTRUCTOR;
		}
	}

	/**
	 * Returns a list of archived sticker sets.
	 * <p> Returns {@link StickerSets StickerSets} </p>
	**/
	public static final class GetArchivedStickerSets extends Function<StickerSets> {


		/**
		 * Type of the sticker sets to return.
		**/
		public StickerType stickerType;

		/**
		 * Identifier of the sticker set from which to return the result.
		**/
		public long offsetStickerSetId;

		/**
		 * The maximum number of sticker sets to return; up to 100.
		**/
		public int limit;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1001931341;

		/**
		 * Returns a list of archived sticker sets.
		 *
		 * <p> Returns {@link StickerSets StickerSets} </p>
		**/
		public GetArchivedStickerSets() {}

		/**
		 * Returns a list of archived sticker sets.
		 *
		 * <p> Returns {@link StickerSets StickerSets} </p>
		 *
		 * @param stickerType Type of the sticker sets to return.
		 * @param offsetStickerSetId Identifier of the sticker set from which to return the result.
		 * @param limit The maximum number of sticker sets to return; up to 100.
		 *
		 * <p> Returns {@link StickerSets StickerSets} </p>
		**/
		public GetArchivedStickerSets(StickerType stickerType, long offsetStickerSetId, int limit) {
			this.stickerType = stickerType;
			this.offsetStickerSetId = offsetStickerSetId;
			this.limit = limit;
		}

		/**
		 * Returns a list of archived sticker sets.
		 *
		 * <p> Returns {@link StickerSets StickerSets} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetArchivedStickerSets(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case StickerTypeRegular.CONSTRUCTOR: this.stickerType = new StickerTypeRegular(input); break;
					case StickerTypeMask.CONSTRUCTOR: this.stickerType = new StickerTypeMask(input); break;
					case StickerTypeCustomEmoji.CONSTRUCTOR: this.stickerType = new StickerTypeCustomEmoji(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.offsetStickerSetId = input.readLong();
			this.limit = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetArchivedStickerSets.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetArchivedStickerSets.CONSTRUCTOR);
			if (this.stickerType == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.stickerType.serialize(output);
			}
			output.writeLong(this.offsetStickerSetId);
			output.writeInt(this.limit);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetArchivedStickerSets getArchivedStickerSets = (GetArchivedStickerSets) o;
			if (!Objects.equals(this.stickerType, getArchivedStickerSets.stickerType)) {
				return false;
			}
			if (this.offsetStickerSetId != getArchivedStickerSets.offsetStickerSetId) {
				return false;
			}
			if (this.limit != getArchivedStickerSets.limit) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.offsetStickerSetId);
			result = result * 31 + (this.stickerType == null ? 0 : this.stickerType.hashCode());
			return result;
		}
	}

	/**
	 * Returns a list of sticker sets attached to a file, including regular,
	 * mask, and emoji sticker sets. Currently, only animations, photos, and
	 * videos can have attached sticker sets.
	 * <p> Returns {@link StickerSets StickerSets} </p>
	**/
	public static final class GetAttachedStickerSets extends Function<StickerSets> {


		/**
		 * File identifier.
		**/
		public int fileId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1302172429;

		/**
		 * Returns a list of sticker sets attached to a file, including regular, mask, and emoji sticker sets. Currently, only animations, photos, and videos can have attached sticker sets.
		 *
		 * <p> Returns {@link StickerSets StickerSets} </p>
		**/
		public GetAttachedStickerSets() {}

		/**
		 * Returns a list of sticker sets attached to a file, including regular, mask, and emoji sticker sets. Currently, only animations, photos, and videos can have attached sticker sets.
		 *
		 * <p> Returns {@link StickerSets StickerSets} </p>
		 *
		 * @param fileId File identifier.
		 *
		 * <p> Returns {@link StickerSets StickerSets} </p>
		**/
		public GetAttachedStickerSets(int fileId) {
			this.fileId = fileId;
		}

		/**
		 * Returns a list of sticker sets attached to a file, including regular, mask, and emoji sticker sets. Currently, only animations, photos, and videos can have attached sticker sets.
		 *
		 * <p> Returns {@link StickerSets StickerSets} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetAttachedStickerSets(DataInput input) throws IOException {
			this.fileId = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetAttachedStickerSets.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetAttachedStickerSets.CONSTRUCTOR);
			output.writeInt(this.fileId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetAttachedStickerSets getAttachedStickerSets = (GetAttachedStickerSets) o;
			if (this.fileId != getAttachedStickerSets.fileId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.fileId);
		}
	}

	/**
	 * Returns information about a bot that can be added to attachment menu.
	 * <p> Returns {@link AttachmentMenuBot AttachmentMenuBot} </p>
	**/
	public static final class GetAttachmentMenuBot extends Function<AttachmentMenuBot> {


		/**
		 * Bot&#039;s user identifier.
		**/
		public long botUserId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1034248699;

		/**
		 * Returns information about a bot that can be added to attachment menu.
		 *
		 * <p> Returns {@link AttachmentMenuBot AttachmentMenuBot} </p>
		**/
		public GetAttachmentMenuBot() {}

		/**
		 * Returns information about a bot that can be added to attachment menu.
		 *
		 * <p> Returns {@link AttachmentMenuBot AttachmentMenuBot} </p>
		 *
		 * @param botUserId Bot&#039;s user identifier.
		 *
		 * <p> Returns {@link AttachmentMenuBot AttachmentMenuBot} </p>
		**/
		public GetAttachmentMenuBot(long botUserId) {
			this.botUserId = botUserId;
		}

		/**
		 * Returns information about a bot that can be added to attachment menu.
		 *
		 * <p> Returns {@link AttachmentMenuBot AttachmentMenuBot} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetAttachmentMenuBot(DataInput input) throws IOException {
			this.botUserId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetAttachmentMenuBot.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetAttachmentMenuBot.CONSTRUCTOR);
			output.writeLong(this.botUserId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetAttachmentMenuBot getAttachmentMenuBot = (GetAttachmentMenuBot) o;
			if (this.botUserId != getAttachmentMenuBot.botUserId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.botUserId);
		}
	}

	/**
	 * Returns the current authorization state; this is an offline request.
	 * For informational purposes only. Use updateAuthorizationState instead
	 * to maintain the current authorization state. Can be called before
	 * initialization.
	 * <p> Returns {@link AuthorizationState AuthorizationState} </p>
	**/
	public static final class GetAuthorizationState extends Function<AuthorizationState> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1949154877;

		/**
		 * Returns the current authorization state; this is an offline request. For informational purposes only. Use updateAuthorizationState instead to maintain the current authorization state. Can be called before initialization.
		 *
		 * <p> Returns {@link AuthorizationState AuthorizationState} </p>
		**/
		public GetAuthorizationState() {}

		/**
		 * Returns the current authorization state; this is an offline request. For informational purposes only. Use updateAuthorizationState instead to maintain the current authorization state. Can be called before initialization.
		 *
		 * <p> Returns {@link AuthorizationState AuthorizationState} </p>
		 *
		 *
		 * <p> Returns {@link AuthorizationState AuthorizationState} </p>
		**/

		/**
		 * Returns the current authorization state; this is an offline request. For informational purposes only. Use updateAuthorizationState instead to maintain the current authorization state. Can be called before initialization.
		 *
		 * <p> Returns {@link AuthorizationState AuthorizationState} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetAuthorizationState(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetAuthorizationState.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetAuthorizationState.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return GetAuthorizationState.CONSTRUCTOR;
		}
	}

	/**
	 * Returns auto-download settings presets for the current user.
	 * <p> Returns {@link AutoDownloadSettingsPresets
	 * AutoDownloadSettingsPresets} </p>
	**/
	public static final class GetAutoDownloadSettingsPresets extends Function<AutoDownloadSettingsPresets> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1721088201;

		/**
		 * Returns auto-download settings presets for the current user.
		 *
		 * <p> Returns {@link AutoDownloadSettingsPresets AutoDownloadSettingsPresets} </p>
		**/
		public GetAutoDownloadSettingsPresets() {}

		/**
		 * Returns auto-download settings presets for the current user.
		 *
		 * <p> Returns {@link AutoDownloadSettingsPresets AutoDownloadSettingsPresets} </p>
		 *
		 *
		 * <p> Returns {@link AutoDownloadSettingsPresets AutoDownloadSettingsPresets} </p>
		**/

		/**
		 * Returns auto-download settings presets for the current user.
		 *
		 * <p> Returns {@link AutoDownloadSettingsPresets AutoDownloadSettingsPresets} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetAutoDownloadSettingsPresets(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetAutoDownloadSettingsPresets.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetAutoDownloadSettingsPresets.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return GetAutoDownloadSettingsPresets.CONSTRUCTOR;
		}
	}

	/**
	 * Returns autosave settings for the current user.
	 * <p> Returns {@link AutosaveSettings AutosaveSettings} </p>
	**/
	public static final class GetAutosaveSettings extends Function<AutosaveSettings> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2136207914;

		/**
		 * Returns autosave settings for the current user.
		 *
		 * <p> Returns {@link AutosaveSettings AutosaveSettings} </p>
		**/
		public GetAutosaveSettings() {}

		/**
		 * Returns autosave settings for the current user.
		 *
		 * <p> Returns {@link AutosaveSettings AutosaveSettings} </p>
		 *
		 *
		 * <p> Returns {@link AutosaveSettings AutosaveSettings} </p>
		**/

		/**
		 * Returns autosave settings for the current user.
		 *
		 * <p> Returns {@link AutosaveSettings AutosaveSettings} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetAutosaveSettings(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetAutosaveSettings.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetAutosaveSettings.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return GetAutosaveSettings.CONSTRUCTOR;
		}
	}

	/**
	 * Constructs a persistent HTTP URL for a background.
	 * <p> Returns {@link HttpUrl HttpUrl} </p>
	**/
	public static final class GetBackgroundUrl extends Function<HttpUrl> {


		/**
		 * Background name.
		**/
		public String name;

		/**
		 * Background type.
		**/
		public BackgroundType type;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 733769682;

		/**
		 * Constructs a persistent HTTP URL for a background.
		 *
		 * <p> Returns {@link HttpUrl HttpUrl} </p>
		**/
		public GetBackgroundUrl() {}

		/**
		 * Constructs a persistent HTTP URL for a background.
		 *
		 * <p> Returns {@link HttpUrl HttpUrl} </p>
		 *
		 * @param name Background name.
		 * @param type Background type.
		 *
		 * <p> Returns {@link HttpUrl HttpUrl} </p>
		**/
		public GetBackgroundUrl(String name, BackgroundType type) {
			this.name = name;
			this.type = type;
		}

		/**
		 * Constructs a persistent HTTP URL for a background.
		 *
		 * <p> Returns {@link HttpUrl HttpUrl} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetBackgroundUrl(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] nameTmp = new byte[input.readInt()];
				input.readFully(nameTmp);
				this.name = new String(nameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case BackgroundTypeWallpaper.CONSTRUCTOR: this.type = new BackgroundTypeWallpaper(input); break;
					case BackgroundTypePattern.CONSTRUCTOR: this.type = new BackgroundTypePattern(input); break;
					case BackgroundTypeFill.CONSTRUCTOR: this.type = new BackgroundTypeFill(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetBackgroundUrl.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetBackgroundUrl.CONSTRUCTOR);
			if (this.name == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nameTmp = this.name.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nameTmp.length);
				output.write(nameTmp);
			}
			if (this.type == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.type.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetBackgroundUrl getBackgroundUrl = (GetBackgroundUrl) o;
			if (this.name != getBackgroundUrl.name) {
				return false;
			}
			if (!Objects.equals(this.type, getBackgroundUrl.type)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.name == null ? 0 : this.name.hashCode();
			result = result * 31 + (this.type == null ? 0 : this.type.hashCode());
			return result;
		}
	}

	/**
	 * Returns backgrounds installed by the user.
	 * <p> Returns {@link Backgrounds Backgrounds} </p>
	**/
	public static final class GetBackgrounds extends Function<Backgrounds> {


		/**
		 * Pass true to order returned backgrounds for a dark theme.
		**/
		public boolean forDarkTheme;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 249072633;

		/**
		 * Returns backgrounds installed by the user.
		 *
		 * <p> Returns {@link Backgrounds Backgrounds} </p>
		**/
		public GetBackgrounds() {}

		/**
		 * Returns backgrounds installed by the user.
		 *
		 * <p> Returns {@link Backgrounds Backgrounds} </p>
		 *
		 * @param forDarkTheme Pass true to order returned backgrounds for a dark theme.
		 *
		 * <p> Returns {@link Backgrounds Backgrounds} </p>
		**/
		public GetBackgrounds(boolean forDarkTheme) {
			this.forDarkTheme = forDarkTheme;
		}

		/**
		 * Returns backgrounds installed by the user.
		 *
		 * <p> Returns {@link Backgrounds Backgrounds} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetBackgrounds(DataInput input) throws IOException {
			this.forDarkTheme = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetBackgrounds.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetBackgrounds.CONSTRUCTOR);
			output.writeBoolean(this.forDarkTheme);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetBackgrounds getBackgrounds = (GetBackgrounds) o;
			if (this.forDarkTheme != getBackgrounds.forDarkTheme) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Boolean.hashCode(this.forDarkTheme);
		}
	}

	/**
	 * Returns information about a bank card.
	 * <p> Returns {@link BankCardInfo BankCardInfo} </p>
	**/
	public static final class GetBankCardInfo extends Function<BankCardInfo> {


		/**
		 * The bank card number.
		**/
		public String bankCardNumber;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1310515792;

		/**
		 * Returns information about a bank card.
		 *
		 * <p> Returns {@link BankCardInfo BankCardInfo} </p>
		**/
		public GetBankCardInfo() {}

		/**
		 * Returns information about a bank card.
		 *
		 * <p> Returns {@link BankCardInfo BankCardInfo} </p>
		 *
		 * @param bankCardNumber The bank card number.
		 *
		 * <p> Returns {@link BankCardInfo BankCardInfo} </p>
		**/
		public GetBankCardInfo(String bankCardNumber) {
			this.bankCardNumber = bankCardNumber;
		}

		/**
		 * Returns information about a bank card.
		 *
		 * <p> Returns {@link BankCardInfo BankCardInfo} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetBankCardInfo(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] bankCardNumberTmp = new byte[input.readInt()];
				input.readFully(bankCardNumberTmp);
				this.bankCardNumber = new String(bankCardNumberTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetBankCardInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetBankCardInfo.CONSTRUCTOR);
			if (this.bankCardNumber == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] bankCardNumberTmp = this.bankCardNumber.getBytes(StandardCharsets.UTF_8);
				output.writeInt(bankCardNumberTmp.length);
				output.write(bankCardNumberTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetBankCardInfo getBankCardInfo = (GetBankCardInfo) o;
			if (this.bankCardNumber != getBankCardInfo.bankCardNumber) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.bankCardNumber == null ? 0 : this.bankCardNumber.hashCode();
		}
	}

	/**
	 * Returns information about a basic group by its identifier. This is an
	 * offline request if the current user is not a bot.
	 * <p> Returns {@link BasicGroup BasicGroup} </p>
	**/
	public static final class GetBasicGroup extends Function<BasicGroup> {


		/**
		 * Basic group identifier.
		**/
		public long basicGroupId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1635174828;

		/**
		 * Returns information about a basic group by its identifier. This is an offline request if the current user is not a bot.
		 *
		 * <p> Returns {@link BasicGroup BasicGroup} </p>
		**/
		public GetBasicGroup() {}

		/**
		 * Returns information about a basic group by its identifier. This is an offline request if the current user is not a bot.
		 *
		 * <p> Returns {@link BasicGroup BasicGroup} </p>
		 *
		 * @param basicGroupId Basic group identifier.
		 *
		 * <p> Returns {@link BasicGroup BasicGroup} </p>
		**/
		public GetBasicGroup(long basicGroupId) {
			this.basicGroupId = basicGroupId;
		}

		/**
		 * Returns information about a basic group by its identifier. This is an offline request if the current user is not a bot.
		 *
		 * <p> Returns {@link BasicGroup BasicGroup} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetBasicGroup(DataInput input) throws IOException {
			this.basicGroupId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetBasicGroup.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetBasicGroup.CONSTRUCTOR);
			output.writeLong(this.basicGroupId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetBasicGroup getBasicGroup = (GetBasicGroup) o;
			if (this.basicGroupId != getBasicGroup.basicGroupId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.basicGroupId);
		}
	}

	/**
	 * Returns full information about a basic group by its identifier.
	 * <p> Returns {@link BasicGroupFullInfo BasicGroupFullInfo} </p>
	**/
	public static final class GetBasicGroupFullInfo extends Function<BasicGroupFullInfo> {


		/**
		 * Basic group identifier.
		**/
		public long basicGroupId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1822039253;

		/**
		 * Returns full information about a basic group by its identifier.
		 *
		 * <p> Returns {@link BasicGroupFullInfo BasicGroupFullInfo} </p>
		**/
		public GetBasicGroupFullInfo() {}

		/**
		 * Returns full information about a basic group by its identifier.
		 *
		 * <p> Returns {@link BasicGroupFullInfo BasicGroupFullInfo} </p>
		 *
		 * @param basicGroupId Basic group identifier.
		 *
		 * <p> Returns {@link BasicGroupFullInfo BasicGroupFullInfo} </p>
		**/
		public GetBasicGroupFullInfo(long basicGroupId) {
			this.basicGroupId = basicGroupId;
		}

		/**
		 * Returns full information about a basic group by its identifier.
		 *
		 * <p> Returns {@link BasicGroupFullInfo BasicGroupFullInfo} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetBasicGroupFullInfo(DataInput input) throws IOException {
			this.basicGroupId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetBasicGroupFullInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetBasicGroupFullInfo.CONSTRUCTOR);
			output.writeLong(this.basicGroupId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetBasicGroupFullInfo getBasicGroupFullInfo = (GetBasicGroupFullInfo) o;
			if (this.basicGroupId != getBasicGroupFullInfo.basicGroupId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.basicGroupId);
		}
	}

	/**
	 * Returns users and chats that were blocked by the current user.
	 * <p> Returns {@link MessageSenders MessageSenders} </p>
	**/
	public static final class GetBlockedMessageSenders extends Function<MessageSenders> {


		/**
		 * Number of users and chats to skip in the result; must be non-negative.
		**/
		public int offset;

		/**
		 * The maximum number of users and chats to return; up to 100.
		**/
		public int limit;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1947079776;

		/**
		 * Returns users and chats that were blocked by the current user.
		 *
		 * <p> Returns {@link MessageSenders MessageSenders} </p>
		**/
		public GetBlockedMessageSenders() {}

		/**
		 * Returns users and chats that were blocked by the current user.
		 *
		 * <p> Returns {@link MessageSenders MessageSenders} </p>
		 *
		 * @param offset Number of users and chats to skip in the result; must be non-negative.
		 * @param limit The maximum number of users and chats to return; up to 100.
		 *
		 * <p> Returns {@link MessageSenders MessageSenders} </p>
		**/
		public GetBlockedMessageSenders(int offset, int limit) {
			this.offset = offset;
			this.limit = limit;
		}

		/**
		 * Returns users and chats that were blocked by the current user.
		 *
		 * <p> Returns {@link MessageSenders MessageSenders} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetBlockedMessageSenders(DataInput input) throws IOException {
			this.offset = input.readInt();
			this.limit = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetBlockedMessageSenders.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetBlockedMessageSenders.CONSTRUCTOR);
			output.writeInt(this.offset);
			output.writeInt(this.limit);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetBlockedMessageSenders getBlockedMessageSenders = (GetBlockedMessageSenders) o;
			if (this.offset != getBlockedMessageSenders.offset) {
				return false;
			}
			if (this.limit != getBlockedMessageSenders.limit) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.offset);
			return result;
		}
	}

	/**
	 * Returns the text shown in the chat with a bot if the chat is empty in
	 * the given language. Can be called only if userTypeBot.canBeEdited ==
	 * true.
	 * <p> Returns {@link Text Text} </p>
	**/
	public static final class GetBotInfoDescription extends Function<Text> {


		/**
		 * Identifier of the target bot.
		**/
		public long botUserId;

		/**
		 * A two-letter ISO 639-1 language code or an empty string.
		**/
		public String languageCode;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -762841035;

		/**
		 * Returns the text shown in the chat with a bot if the chat is empty in the given language. Can be called only if userTypeBot.canBeEdited == true.
		 *
		 * <p> Returns {@link Text Text} </p>
		**/
		public GetBotInfoDescription() {}

		/**
		 * Returns the text shown in the chat with a bot if the chat is empty in the given language. Can be called only if userTypeBot.canBeEdited == true.
		 *
		 * <p> Returns {@link Text Text} </p>
		 *
		 * @param botUserId Identifier of the target bot.
		 * @param languageCode A two-letter ISO 639-1 language code or an empty string.
		 *
		 * <p> Returns {@link Text Text} </p>
		**/
		public GetBotInfoDescription(long botUserId, String languageCode) {
			this.botUserId = botUserId;
			this.languageCode = languageCode;
		}

		/**
		 * Returns the text shown in the chat with a bot if the chat is empty in the given language. Can be called only if userTypeBot.canBeEdited == true.
		 *
		 * <p> Returns {@link Text Text} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetBotInfoDescription(DataInput input) throws IOException {
			this.botUserId = input.readLong();
			if (input.readBoolean()) {
				byte[] languageCodeTmp = new byte[input.readInt()];
				input.readFully(languageCodeTmp);
				this.languageCode = new String(languageCodeTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetBotInfoDescription.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetBotInfoDescription.CONSTRUCTOR);
			output.writeLong(this.botUserId);
			if (this.languageCode == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] languageCodeTmp = this.languageCode.getBytes(StandardCharsets.UTF_8);
				output.writeInt(languageCodeTmp.length);
				output.write(languageCodeTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetBotInfoDescription getBotInfoDescription = (GetBotInfoDescription) o;
			if (this.botUserId != getBotInfoDescription.botUserId) {
				return false;
			}
			if (this.languageCode != getBotInfoDescription.languageCode) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.botUserId);
			result = result * 31 + (this.languageCode == null ? 0 : this.languageCode.hashCode());
			return result;
		}
	}

	/**
	 * Returns the text shown on a bot&#039;s profile page and sent together
	 * with the link when users share the bot in the given language. Can be
	 * called only if userTypeBot.canBeEdited == true.
	 * <p> Returns {@link Text Text} </p>
	**/
	public static final class GetBotInfoShortDescription extends Function<Text> {


		/**
		 * Identifier of the target bot.
		**/
		public long botUserId;

		/**
		 * A two-letter ISO 639-1 language code or an empty string.
		**/
		public String languageCode;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1243358740;

		/**
		 * Returns the text shown on a bot&#039;s profile page and sent together with the link when users share the bot in the given language. Can be called only if userTypeBot.canBeEdited == true.
		 *
		 * <p> Returns {@link Text Text} </p>
		**/
		public GetBotInfoShortDescription() {}

		/**
		 * Returns the text shown on a bot&#039;s profile page and sent together with the link when users share the bot in the given language. Can be called only if userTypeBot.canBeEdited == true.
		 *
		 * <p> Returns {@link Text Text} </p>
		 *
		 * @param botUserId Identifier of the target bot.
		 * @param languageCode A two-letter ISO 639-1 language code or an empty string.
		 *
		 * <p> Returns {@link Text Text} </p>
		**/
		public GetBotInfoShortDescription(long botUserId, String languageCode) {
			this.botUserId = botUserId;
			this.languageCode = languageCode;
		}

		/**
		 * Returns the text shown on a bot&#039;s profile page and sent together with the link when users share the bot in the given language. Can be called only if userTypeBot.canBeEdited == true.
		 *
		 * <p> Returns {@link Text Text} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetBotInfoShortDescription(DataInput input) throws IOException {
			this.botUserId = input.readLong();
			if (input.readBoolean()) {
				byte[] languageCodeTmp = new byte[input.readInt()];
				input.readFully(languageCodeTmp);
				this.languageCode = new String(languageCodeTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetBotInfoShortDescription.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetBotInfoShortDescription.CONSTRUCTOR);
			output.writeLong(this.botUserId);
			if (this.languageCode == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] languageCodeTmp = this.languageCode.getBytes(StandardCharsets.UTF_8);
				output.writeInt(languageCodeTmp.length);
				output.write(languageCodeTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetBotInfoShortDescription getBotInfoShortDescription = (GetBotInfoShortDescription) o;
			if (this.botUserId != getBotInfoShortDescription.botUserId) {
				return false;
			}
			if (this.languageCode != getBotInfoShortDescription.languageCode) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.botUserId);
			result = result * 31 + (this.languageCode == null ? 0 : this.languageCode.hashCode());
			return result;
		}
	}

	/**
	 * Returns the name of a bot in the given language. Can be called only
	 * if userTypeBot.canBeEdited == true.
	 * <p> Returns {@link Text Text} </p>
	**/
	public static final class GetBotName extends Function<Text> {


		/**
		 * Identifier of the target bot.
		**/
		public long botUserId;

		/**
		 * A two-letter ISO 639-1 language code or an empty string.
		**/
		public String languageCode;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1707118036;

		/**
		 * Returns the name of a bot in the given language. Can be called only if userTypeBot.canBeEdited == true.
		 *
		 * <p> Returns {@link Text Text} </p>
		**/
		public GetBotName() {}

		/**
		 * Returns the name of a bot in the given language. Can be called only if userTypeBot.canBeEdited == true.
		 *
		 * <p> Returns {@link Text Text} </p>
		 *
		 * @param botUserId Identifier of the target bot.
		 * @param languageCode A two-letter ISO 639-1 language code or an empty string.
		 *
		 * <p> Returns {@link Text Text} </p>
		**/
		public GetBotName(long botUserId, String languageCode) {
			this.botUserId = botUserId;
			this.languageCode = languageCode;
		}

		/**
		 * Returns the name of a bot in the given language. Can be called only if userTypeBot.canBeEdited == true.
		 *
		 * <p> Returns {@link Text Text} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetBotName(DataInput input) throws IOException {
			this.botUserId = input.readLong();
			if (input.readBoolean()) {
				byte[] languageCodeTmp = new byte[input.readInt()];
				input.readFully(languageCodeTmp);
				this.languageCode = new String(languageCodeTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetBotName.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetBotName.CONSTRUCTOR);
			output.writeLong(this.botUserId);
			if (this.languageCode == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] languageCodeTmp = this.languageCode.getBytes(StandardCharsets.UTF_8);
				output.writeInt(languageCodeTmp.length);
				output.write(languageCodeTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetBotName getBotName = (GetBotName) o;
			if (this.botUserId != getBotName.botUserId) {
				return false;
			}
			if (this.languageCode != getBotName.languageCode) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.botUserId);
			result = result * 31 + (this.languageCode == null ? 0 : this.languageCode.hashCode());
			return result;
		}
	}

	/**
	 * Sends a callback query to a bot and returns an answer. Returns an
	 * error with code 502 if the bot fails to answer the query before the
	 * query timeout expires.
	 * <p> Returns {@link CallbackQueryAnswer CallbackQueryAnswer} </p>
	**/
	public static final class GetCallbackQueryAnswer extends Function<CallbackQueryAnswer> {


		/**
		 * Identifier of the chat with the message.
		**/
		public long chatId;

		/**
		 * Identifier of the message from which the query originated.
		**/
		public long messageId;

		/**
		 * Query payload.
		**/
		public CallbackQueryPayload payload;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 116357727;

		/**
		 * Sends a callback query to a bot and returns an answer. Returns an error with code 502 if the bot fails to answer the query before the query timeout expires.
		 *
		 * <p> Returns {@link CallbackQueryAnswer CallbackQueryAnswer} </p>
		**/
		public GetCallbackQueryAnswer() {}

		/**
		 * Sends a callback query to a bot and returns an answer. Returns an error with code 502 if the bot fails to answer the query before the query timeout expires.
		 *
		 * <p> Returns {@link CallbackQueryAnswer CallbackQueryAnswer} </p>
		 *
		 * @param chatId Identifier of the chat with the message.
		 * @param messageId Identifier of the message from which the query originated.
		 * @param payload Query payload.
		 *
		 * <p> Returns {@link CallbackQueryAnswer CallbackQueryAnswer} </p>
		**/
		public GetCallbackQueryAnswer(long chatId, long messageId, CallbackQueryPayload payload) {
			this.chatId = chatId;
			this.messageId = messageId;
			this.payload = payload;
		}

		/**
		 * Sends a callback query to a bot and returns an answer. Returns an error with code 502 if the bot fails to answer the query before the query timeout expires.
		 *
		 * <p> Returns {@link CallbackQueryAnswer CallbackQueryAnswer} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetCallbackQueryAnswer(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case CallbackQueryPayloadData.CONSTRUCTOR: this.payload = new CallbackQueryPayloadData(input); break;
					case CallbackQueryPayloadDataWithPassword.CONSTRUCTOR: this.payload = new CallbackQueryPayloadDataWithPassword(input); break;
					case CallbackQueryPayloadGame.CONSTRUCTOR: this.payload = new CallbackQueryPayloadGame(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetCallbackQueryAnswer.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetCallbackQueryAnswer.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
			if (this.payload == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.payload.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetCallbackQueryAnswer getCallbackQueryAnswer = (GetCallbackQueryAnswer) o;
			if (this.chatId != getCallbackQueryAnswer.chatId) {
				return false;
			}
			if (this.messageId != getCallbackQueryAnswer.messageId) {
				return false;
			}
			if (!Objects.equals(this.payload, getCallbackQueryAnswer.payload)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.payload == null ? 0 : this.payload.hashCode());
			return result;
		}
	}

	/**
	 * Returns information about a message with the callback button that
	 * originated a callback query; for bots only.
	 * <p> Returns {@link Message Message} </p>
	**/
	public static final class GetCallbackQueryMessage extends Function<Message> {


		/**
		 * Identifier of the chat the message belongs to.
		**/
		public long chatId;

		/**
		 * Message identifier.
		**/
		public long messageId;

		/**
		 * Identifier of the callback query.
		**/
		public long callbackQueryId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1121939086;

		/**
		 * Returns information about a message with the callback button that originated a callback query; for bots only.
		 *
		 * <p> Returns {@link Message Message} </p>
		**/
		public GetCallbackQueryMessage() {}

		/**
		 * Returns information about a message with the callback button that originated a callback query; for bots only.
		 *
		 * <p> Returns {@link Message Message} </p>
		 *
		 * @param chatId Identifier of the chat the message belongs to.
		 * @param messageId Message identifier.
		 * @param callbackQueryId Identifier of the callback query.
		 *
		 * <p> Returns {@link Message Message} </p>
		**/
		public GetCallbackQueryMessage(long chatId, long messageId, long callbackQueryId) {
			this.chatId = chatId;
			this.messageId = messageId;
			this.callbackQueryId = callbackQueryId;
		}

		/**
		 * Returns information about a message with the callback button that originated a callback query; for bots only.
		 *
		 * <p> Returns {@link Message Message} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetCallbackQueryMessage(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
			this.callbackQueryId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetCallbackQueryMessage.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetCallbackQueryMessage.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
			output.writeLong(this.callbackQueryId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetCallbackQueryMessage getCallbackQueryMessage = (GetCallbackQueryMessage) o;
			if (this.chatId != getCallbackQueryMessage.chatId) {
				return false;
			}
			if (this.messageId != getCallbackQueryMessage.messageId) {
				return false;
			}
			if (this.callbackQueryId != getCallbackQueryMessage.callbackQueryId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Returns information about a chat by its identifier, this is an
	 * offline request if the current user is not a bot.
	 * <p> Returns {@link Chat Chat} </p>
	**/
	public static final class GetChat extends Function<Chat> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1866601536;

		/**
		 * Returns information about a chat by its identifier, this is an offline request if the current user is not a bot.
		 *
		 * <p> Returns {@link Chat Chat} </p>
		**/
		public GetChat() {}

		/**
		 * Returns information about a chat by its identifier, this is an offline request if the current user is not a bot.
		 *
		 * <p> Returns {@link Chat Chat} </p>
		 *
		 * @param chatId Chat identifier.
		 *
		 * <p> Returns {@link Chat Chat} </p>
		**/
		public GetChat(long chatId) {
			this.chatId = chatId;
		}

		/**
		 * Returns information about a chat by its identifier, this is an offline request if the current user is not a bot.
		 *
		 * <p> Returns {@link Chat Chat} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetChat(DataInput input) throws IOException {
			this.chatId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetChat.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetChat.CONSTRUCTOR);
			output.writeLong(this.chatId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetChat getChat = (GetChat) o;
			if (this.chatId != getChat.chatId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.chatId);
		}
	}

	/**
	 * Returns a list of administrators of the chat with their custom titles.
	 * <p> Returns {@link ChatAdministrators ChatAdministrators} </p>
	**/
	public static final class GetChatAdministrators extends Function<ChatAdministrators> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1544468155;

		/**
		 * Returns a list of administrators of the chat with their custom titles.
		 *
		 * <p> Returns {@link ChatAdministrators ChatAdministrators} </p>
		**/
		public GetChatAdministrators() {}

		/**
		 * Returns a list of administrators of the chat with their custom titles.
		 *
		 * <p> Returns {@link ChatAdministrators ChatAdministrators} </p>
		 *
		 * @param chatId Chat identifier.
		 *
		 * <p> Returns {@link ChatAdministrators ChatAdministrators} </p>
		**/
		public GetChatAdministrators(long chatId) {
			this.chatId = chatId;
		}

		/**
		 * Returns a list of administrators of the chat with their custom titles.
		 *
		 * <p> Returns {@link ChatAdministrators ChatAdministrators} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetChatAdministrators(DataInput input) throws IOException {
			this.chatId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetChatAdministrators.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetChatAdministrators.CONSTRUCTOR);
			output.writeLong(this.chatId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetChatAdministrators getChatAdministrators = (GetChatAdministrators) o;
			if (this.chatId != getChatAdministrators.chatId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.chatId);
		}
	}

	/**
	 * Returns list of message sender identifiers, which can be used to send
	 * messages in a chat.
	 * <p> Returns {@link ChatMessageSenders ChatMessageSenders} </p>
	**/
	public static final class GetChatAvailableMessageSenders extends Function<ChatMessageSenders> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1158670635;

		/**
		 * Returns list of message sender identifiers, which can be used to send messages in a chat.
		 *
		 * <p> Returns {@link ChatMessageSenders ChatMessageSenders} </p>
		**/
		public GetChatAvailableMessageSenders() {}

		/**
		 * Returns list of message sender identifiers, which can be used to send messages in a chat.
		 *
		 * <p> Returns {@link ChatMessageSenders ChatMessageSenders} </p>
		 *
		 * @param chatId Chat identifier.
		 *
		 * <p> Returns {@link ChatMessageSenders ChatMessageSenders} </p>
		**/
		public GetChatAvailableMessageSenders(long chatId) {
			this.chatId = chatId;
		}

		/**
		 * Returns list of message sender identifiers, which can be used to send messages in a chat.
		 *
		 * <p> Returns {@link ChatMessageSenders ChatMessageSenders} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetChatAvailableMessageSenders(DataInput input) throws IOException {
			this.chatId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetChatAvailableMessageSenders.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetChatAvailableMessageSenders.CONSTRUCTOR);
			output.writeLong(this.chatId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetChatAvailableMessageSenders getChatAvailableMessageSenders = (GetChatAvailableMessageSenders) o;
			if (this.chatId != getChatAvailableMessageSenders.chatId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.chatId);
		}
	}

	/**
	 * Returns a list of service actions taken by chat members and
	 * administrators in the last 48 hours. Available only for supergroups
	 * and channels. Requires administrator rights. Returns results in
	 * reverse chronological order (i.e., in order of decreasing eventId).
	 * <p> Returns {@link ChatEvents ChatEvents} </p>
	**/
	public static final class GetChatEventLog extends Function<ChatEvents> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Search query by which to filter events.
		**/
		public String query;

		/**
		 * Identifier of an event from which to return results. Use 0 to get results from the latest events.
		**/
		public long fromEventId;

		/**
		 * The maximum number of events to return; up to 100.
		**/
		public int limit;

		/**
		 * The types of events to return; pass null to get chat events of all types.
		**/
		public ChatEventLogFilters filters;

		/**
		 * User identifiers by which to filter events. By default, events relating to all users will be returned.
		**/
		public long[] userIds;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1281344669;

		/**
		 * Returns a list of service actions taken by chat members and administrators in the last 48 hours. Available only for supergroups and channels. Requires administrator rights. Returns results in reverse chronological order (i.e., in order of decreasing eventId).
		 *
		 * <p> Returns {@link ChatEvents ChatEvents} </p>
		**/
		public GetChatEventLog() {}

		/**
		 * Returns a list of service actions taken by chat members and administrators in the last 48 hours. Available only for supergroups and channels. Requires administrator rights. Returns results in reverse chronological order (i.e., in order of decreasing eventId).
		 *
		 * <p> Returns {@link ChatEvents ChatEvents} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param query Search query by which to filter events.
		 * @param fromEventId Identifier of an event from which to return results. Use 0 to get results from the latest events.
		 * @param limit The maximum number of events to return; up to 100.
		 * @param filters The types of events to return; pass null to get chat events of all types.
		 * @param userIds User identifiers by which to filter events. By default, events relating to all users will be returned.
		 *
		 * <p> Returns {@link ChatEvents ChatEvents} </p>
		**/
		public GetChatEventLog(long chatId,
				String query,
				long fromEventId,
				int limit,
				ChatEventLogFilters filters,
				long[] userIds) {
			this.chatId = chatId;
			this.query = query;
			this.fromEventId = fromEventId;
			this.limit = limit;
			this.filters = filters;
			this.userIds = userIds;
		}

		/**
		 * Returns a list of service actions taken by chat members and administrators in the last 48 hours. Available only for supergroups and channels. Requires administrator rights. Returns results in reverse chronological order (i.e., in order of decreasing eventId).
		 *
		 * <p> Returns {@link ChatEvents ChatEvents} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetChatEventLog(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				byte[] queryTmp = new byte[input.readInt()];
				input.readFully(queryTmp);
				this.query = new String(queryTmp, StandardCharsets.UTF_8);
			}
			this.fromEventId = input.readLong();
			this.limit = input.readInt();
			if (input.readBoolean()) {
				if (ChatEventLogFilters.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.filters = new ChatEventLogFilters(input);
			}
			if (input.readBoolean()) {
				this.userIds = new long[input.readInt()];
				for (int i = 0; i < this.userIds.length; i++) {
					this.userIds[i] = input.readLong();
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetChatEventLog.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetChatEventLog.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.query == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] queryTmp = this.query.getBytes(StandardCharsets.UTF_8);
				output.writeInt(queryTmp.length);
				output.write(queryTmp);
			}
			output.writeLong(this.fromEventId);
			output.writeInt(this.limit);
			if (this.filters == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.filters.serialize(output);
			}
			if (this.userIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.userIds.length);
				for (int i = 0; i < this.userIds.length; i++) {
					output.writeLong(this.userIds[i]);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetChatEventLog getChatEventLog = (GetChatEventLog) o;
			if (this.chatId != getChatEventLog.chatId) {
				return false;
			}
			if (this.query != getChatEventLog.query) {
				return false;
			}
			if (this.fromEventId != getChatEventLog.fromEventId) {
				return false;
			}
			if (this.limit != getChatEventLog.limit) {
				return false;
			}
			if (!Objects.equals(this.filters, getChatEventLog.filters)) {
				return false;
			}
			if (!Arrays.equals(this.userIds, getChatEventLog.userIds)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.query == null ? 0 : this.query.hashCode());
			result = result * 31 + (this.filters == null ? 0 : this.filters.hashCode());
			result = result * 31 + (Arrays.hashCode(this.userIds));
			return result;
		}
	}

	/**
	 * Returns information about a chat folder by its identifier.
	 * <p> Returns {@link ChatFolder ChatFolder} </p>
	**/
	public static final class GetChatFolder extends Function<ChatFolder> {


		/**
		 * Chat folder identifier.
		**/
		public int chatFolderId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 92809880;

		/**
		 * Returns information about a chat folder by its identifier.
		 *
		 * <p> Returns {@link ChatFolder ChatFolder} </p>
		**/
		public GetChatFolder() {}

		/**
		 * Returns information about a chat folder by its identifier.
		 *
		 * <p> Returns {@link ChatFolder ChatFolder} </p>
		 *
		 * @param chatFolderId Chat folder identifier.
		 *
		 * <p> Returns {@link ChatFolder ChatFolder} </p>
		**/
		public GetChatFolder(int chatFolderId) {
			this.chatFolderId = chatFolderId;
		}

		/**
		 * Returns information about a chat folder by its identifier.
		 *
		 * <p> Returns {@link ChatFolder ChatFolder} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetChatFolder(DataInput input) throws IOException {
			this.chatFolderId = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetChatFolder.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetChatFolder.CONSTRUCTOR);
			output.writeInt(this.chatFolderId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetChatFolder getChatFolder = (GetChatFolder) o;
			if (this.chatFolderId != getChatFolder.chatFolderId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.chatFolderId);
		}
	}

	/**
	 * Returns identifiers of pinned or always included chats from a chat
	 * folder, which are suggested to be left when the chat folder is
	 * deleted.
	 * <p> Returns {@link Chats Chats} </p>
	**/
	public static final class GetChatFolderChatsToLeave extends Function<Chats> {


		/**
		 * Chat folder identifier.
		**/
		public int chatFolderId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1916672337;

		/**
		 * Returns identifiers of pinned or always included chats from a chat folder, which are suggested to be left when the chat folder is deleted.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		**/
		public GetChatFolderChatsToLeave() {}

		/**
		 * Returns identifiers of pinned or always included chats from a chat folder, which are suggested to be left when the chat folder is deleted.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		 *
		 * @param chatFolderId Chat folder identifier.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		**/
		public GetChatFolderChatsToLeave(int chatFolderId) {
			this.chatFolderId = chatFolderId;
		}

		/**
		 * Returns identifiers of pinned or always included chats from a chat folder, which are suggested to be left when the chat folder is deleted.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetChatFolderChatsToLeave(DataInput input) throws IOException {
			this.chatFolderId = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetChatFolderChatsToLeave.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetChatFolderChatsToLeave.CONSTRUCTOR);
			output.writeInt(this.chatFolderId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetChatFolderChatsToLeave getChatFolderChatsToLeave = (GetChatFolderChatsToLeave) o;
			if (this.chatFolderId != getChatFolderChatsToLeave.chatFolderId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.chatFolderId);
		}
	}

	/**
	 * Returns default icon name for a folder. Can be called synchronously.
	 * <p> Returns {@link ChatFolderIcon ChatFolderIcon} </p>
	**/
	public static final class GetChatFolderDefaultIconName extends Function<ChatFolderIcon> {


		/**
		 * Chat folder.
		**/
		public ChatFolder folder;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 754425959;

		/**
		 * Returns default icon name for a folder. Can be called synchronously.
		 *
		 * <p> Returns {@link ChatFolderIcon ChatFolderIcon} </p>
		**/
		public GetChatFolderDefaultIconName() {}

		/**
		 * Returns default icon name for a folder. Can be called synchronously.
		 *
		 * <p> Returns {@link ChatFolderIcon ChatFolderIcon} </p>
		 *
		 * @param folder Chat folder.
		 *
		 * <p> Returns {@link ChatFolderIcon ChatFolderIcon} </p>
		**/
		public GetChatFolderDefaultIconName(ChatFolder folder) {
			this.folder = folder;
		}

		/**
		 * Returns default icon name for a folder. Can be called synchronously.
		 *
		 * <p> Returns {@link ChatFolderIcon ChatFolderIcon} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetChatFolderDefaultIconName(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (ChatFolder.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.folder = new ChatFolder(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetChatFolderDefaultIconName.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetChatFolderDefaultIconName.CONSTRUCTOR);
			if (this.folder == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.folder.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetChatFolderDefaultIconName getChatFolderDefaultIconName = (GetChatFolderDefaultIconName) o;
			if (!Objects.equals(this.folder, getChatFolderDefaultIconName.folder)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.folder == null ? 0 : this.folder.hashCode();
		}
	}

	/**
	 * Returns invite links created by the current user for a shareable chat
	 * folder.
	 * <p> Returns {@link ChatFolderInviteLinks ChatFolderInviteLinks} </p>
	**/
	public static final class GetChatFolderInviteLinks extends Function<ChatFolderInviteLinks> {


		/**
		 * Chat folder identifier.
		**/
		public int chatFolderId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 329079776;

		/**
		 * Returns invite links created by the current user for a shareable chat folder.
		 *
		 * <p> Returns {@link ChatFolderInviteLinks ChatFolderInviteLinks} </p>
		**/
		public GetChatFolderInviteLinks() {}

		/**
		 * Returns invite links created by the current user for a shareable chat folder.
		 *
		 * <p> Returns {@link ChatFolderInviteLinks ChatFolderInviteLinks} </p>
		 *
		 * @param chatFolderId Chat folder identifier.
		 *
		 * <p> Returns {@link ChatFolderInviteLinks ChatFolderInviteLinks} </p>
		**/
		public GetChatFolderInviteLinks(int chatFolderId) {
			this.chatFolderId = chatFolderId;
		}

		/**
		 * Returns invite links created by the current user for a shareable chat folder.
		 *
		 * <p> Returns {@link ChatFolderInviteLinks ChatFolderInviteLinks} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetChatFolderInviteLinks(DataInput input) throws IOException {
			this.chatFolderId = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetChatFolderInviteLinks.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetChatFolderInviteLinks.CONSTRUCTOR);
			output.writeInt(this.chatFolderId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetChatFolderInviteLinks getChatFolderInviteLinks = (GetChatFolderInviteLinks) o;
			if (this.chatFolderId != getChatFolderInviteLinks.chatFolderId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.chatFolderId);
		}
	}

	/**
	 * Returns new chats added to a shareable chat folder by its owner. The
	 * method must be called at most once in
	 * getOption(&quot;chat_folder_new_chats_update_period&quot;) for the
	 * given chat folder.
	 * <p> Returns {@link Chats Chats} </p>
	**/
	public static final class GetChatFolderNewChats extends Function<Chats> {


		/**
		 * Chat folder identifier.
		**/
		public int chatFolderId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2123181260;

		/**
		 * Returns new chats added to a shareable chat folder by its owner. The method must be called at most once in getOption(&quot;chat_folder_new_chats_update_period&quot;) for the given chat folder.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		**/
		public GetChatFolderNewChats() {}

		/**
		 * Returns new chats added to a shareable chat folder by its owner. The method must be called at most once in getOption(&quot;chat_folder_new_chats_update_period&quot;) for the given chat folder.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		 *
		 * @param chatFolderId Chat folder identifier.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		**/
		public GetChatFolderNewChats(int chatFolderId) {
			this.chatFolderId = chatFolderId;
		}

		/**
		 * Returns new chats added to a shareable chat folder by its owner. The method must be called at most once in getOption(&quot;chat_folder_new_chats_update_period&quot;) for the given chat folder.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetChatFolderNewChats(DataInput input) throws IOException {
			this.chatFolderId = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetChatFolderNewChats.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetChatFolderNewChats.CONSTRUCTOR);
			output.writeInt(this.chatFolderId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetChatFolderNewChats getChatFolderNewChats = (GetChatFolderNewChats) o;
			if (this.chatFolderId != getChatFolderNewChats.chatFolderId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.chatFolderId);
		}
	}

	/**
	 * Returns messages in a chat. The messages are returned in a reverse
	 * chronological order (i.e., in order of decreasing messageId). For
	 * optimal performance, the number of returned messages is chosen by
	 * TDLib. This is an offline request if onlyLocal is true.
	 * <p> Returns {@link Messages Messages} </p>
	**/
	public static final class GetChatHistory extends Function<Messages> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Identifier of the message starting from which history must be fetched; use 0 to get results from the last message.
		**/
		public long fromMessageId;

		/**
		 * Specify 0 to get results from exactly the fromMessageId or a negative offset up to 99 to get additionally some newer messages.
		**/
		public int offset;

		/**
		 * The maximum number of messages to be returned; must be positive and can&#039;t be greater than 100. If the offset is negative, the limit must be greater than or equal to -offset. For optimal performance, the number of returned messages is chosen by TDLib and can be smaller than the specified limit.
		**/
		public int limit;

		/**
		 * Pass true to get only messages that are available without sending network requests.
		**/
		public boolean onlyLocal;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -799960451;

		/**
		 * Returns messages in a chat. The messages are returned in a reverse chronological order (i.e., in order of decreasing messageId). For optimal performance, the number of returned messages is chosen by TDLib. This is an offline request if onlyLocal is true.
		 *
		 * <p> Returns {@link Messages Messages} </p>
		**/
		public GetChatHistory() {}

		/**
		 * Returns messages in a chat. The messages are returned in a reverse chronological order (i.e., in order of decreasing messageId). For optimal performance, the number of returned messages is chosen by TDLib. This is an offline request if onlyLocal is true.
		 *
		 * <p> Returns {@link Messages Messages} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param fromMessageId Identifier of the message starting from which history must be fetched; use 0 to get results from the last message.
		 * @param offset Specify 0 to get results from exactly the fromMessageId or a negative offset up to 99 to get additionally some newer messages.
		 * @param limit The maximum number of messages to be returned; must be positive and can&#039;t be greater than 100. If the offset is negative, the limit must be greater than or equal to -offset. For optimal performance, the number of returned messages is chosen by TDLib and can be smaller than the specified limit.
		 * @param onlyLocal Pass true to get only messages that are available without sending network requests.
		 *
		 * <p> Returns {@link Messages Messages} </p>
		**/
		public GetChatHistory(long chatId,
				long fromMessageId,
				int offset,
				int limit,
				boolean onlyLocal) {
			this.chatId = chatId;
			this.fromMessageId = fromMessageId;
			this.offset = offset;
			this.limit = limit;
			this.onlyLocal = onlyLocal;
		}

		/**
		 * Returns messages in a chat. The messages are returned in a reverse chronological order (i.e., in order of decreasing messageId). For optimal performance, the number of returned messages is chosen by TDLib. This is an offline request if onlyLocal is true.
		 *
		 * <p> Returns {@link Messages Messages} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetChatHistory(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.fromMessageId = input.readLong();
			this.offset = input.readInt();
			this.limit = input.readInt();
			this.onlyLocal = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetChatHistory.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetChatHistory.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.fromMessageId);
			output.writeInt(this.offset);
			output.writeInt(this.limit);
			output.writeBoolean(this.onlyLocal);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetChatHistory getChatHistory = (GetChatHistory) o;
			if (this.chatId != getChatHistory.chatId) {
				return false;
			}
			if (this.fromMessageId != getChatHistory.fromMessageId) {
				return false;
			}
			if (this.offset != getChatHistory.offset) {
				return false;
			}
			if (this.limit != getChatHistory.limit) {
				return false;
			}
			if (this.onlyLocal != getChatHistory.onlyLocal) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Returns information about an invite link. Requires administrator
	 * privileges and canInviteUsers right in the chat to get own links and
	 * owner privileges to get other links.
	 * <p> Returns {@link ChatInviteLink ChatInviteLink} </p>
	**/
	public static final class GetChatInviteLink extends Function<ChatInviteLink> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Invite link to get.
		**/
		public String inviteLink;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -479575555;

		/**
		 * Returns information about an invite link. Requires administrator privileges and canInviteUsers right in the chat to get own links and owner privileges to get other links.
		 *
		 * <p> Returns {@link ChatInviteLink ChatInviteLink} </p>
		**/
		public GetChatInviteLink() {}

		/**
		 * Returns information about an invite link. Requires administrator privileges and canInviteUsers right in the chat to get own links and owner privileges to get other links.
		 *
		 * <p> Returns {@link ChatInviteLink ChatInviteLink} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param inviteLink Invite link to get.
		 *
		 * <p> Returns {@link ChatInviteLink ChatInviteLink} </p>
		**/
		public GetChatInviteLink(long chatId, String inviteLink) {
			this.chatId = chatId;
			this.inviteLink = inviteLink;
		}

		/**
		 * Returns information about an invite link. Requires administrator privileges and canInviteUsers right in the chat to get own links and owner privileges to get other links.
		 *
		 * <p> Returns {@link ChatInviteLink ChatInviteLink} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetChatInviteLink(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				byte[] inviteLinkTmp = new byte[input.readInt()];
				input.readFully(inviteLinkTmp);
				this.inviteLink = new String(inviteLinkTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetChatInviteLink.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetChatInviteLink.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.inviteLink == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] inviteLinkTmp = this.inviteLink.getBytes(StandardCharsets.UTF_8);
				output.writeInt(inviteLinkTmp.length);
				output.write(inviteLinkTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetChatInviteLink getChatInviteLink = (GetChatInviteLink) o;
			if (this.chatId != getChatInviteLink.chatId) {
				return false;
			}
			if (this.inviteLink != getChatInviteLink.inviteLink) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.inviteLink == null ? 0 : this.inviteLink.hashCode());
			return result;
		}
	}

	/**
	 * Returns list of chat administrators with number of their invite
	 * links. Requires owner privileges in the chat.
	 * <p> Returns {@link ChatInviteLinkCounts ChatInviteLinkCounts} </p>
	**/
	public static final class GetChatInviteLinkCounts extends Function<ChatInviteLinkCounts> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 890299025;

		/**
		 * Returns list of chat administrators with number of their invite links. Requires owner privileges in the chat.
		 *
		 * <p> Returns {@link ChatInviteLinkCounts ChatInviteLinkCounts} </p>
		**/
		public GetChatInviteLinkCounts() {}

		/**
		 * Returns list of chat administrators with number of their invite links. Requires owner privileges in the chat.
		 *
		 * <p> Returns {@link ChatInviteLinkCounts ChatInviteLinkCounts} </p>
		 *
		 * @param chatId Chat identifier.
		 *
		 * <p> Returns {@link ChatInviteLinkCounts ChatInviteLinkCounts} </p>
		**/
		public GetChatInviteLinkCounts(long chatId) {
			this.chatId = chatId;
		}

		/**
		 * Returns list of chat administrators with number of their invite links. Requires owner privileges in the chat.
		 *
		 * <p> Returns {@link ChatInviteLinkCounts ChatInviteLinkCounts} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetChatInviteLinkCounts(DataInput input) throws IOException {
			this.chatId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetChatInviteLinkCounts.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetChatInviteLinkCounts.CONSTRUCTOR);
			output.writeLong(this.chatId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetChatInviteLinkCounts getChatInviteLinkCounts = (GetChatInviteLinkCounts) o;
			if (this.chatId != getChatInviteLinkCounts.chatId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.chatId);
		}
	}

	/**
	 * Returns chat members joined a chat via an invite link. Requires
	 * administrator privileges and canInviteUsers right in the chat for own
	 * links and owner privileges for other links.
	 * <p> Returns {@link ChatInviteLinkMembers ChatInviteLinkMembers} </p>
	**/
	public static final class GetChatInviteLinkMembers extends Function<ChatInviteLinkMembers> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Invite link for which to return chat members.
		**/
		public String inviteLink;

		/**
		 * A chat member from which to return next chat members; pass null to get results from the beginning.
		**/
		public ChatInviteLinkMember offsetMember;

		/**
		 * The maximum number of chat members to return; up to 100.
		**/
		public int limit;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -977921638;

		/**
		 * Returns chat members joined a chat via an invite link. Requires administrator privileges and canInviteUsers right in the chat for own links and owner privileges for other links.
		 *
		 * <p> Returns {@link ChatInviteLinkMembers ChatInviteLinkMembers} </p>
		**/
		public GetChatInviteLinkMembers() {}

		/**
		 * Returns chat members joined a chat via an invite link. Requires administrator privileges and canInviteUsers right in the chat for own links and owner privileges for other links.
		 *
		 * <p> Returns {@link ChatInviteLinkMembers ChatInviteLinkMembers} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param inviteLink Invite link for which to return chat members.
		 * @param offsetMember A chat member from which to return next chat members; pass null to get results from the beginning.
		 * @param limit The maximum number of chat members to return; up to 100.
		 *
		 * <p> Returns {@link ChatInviteLinkMembers ChatInviteLinkMembers} </p>
		**/
		public GetChatInviteLinkMembers(long chatId,
				String inviteLink,
				ChatInviteLinkMember offsetMember,
				int limit) {
			this.chatId = chatId;
			this.inviteLink = inviteLink;
			this.offsetMember = offsetMember;
			this.limit = limit;
		}

		/**
		 * Returns chat members joined a chat via an invite link. Requires administrator privileges and canInviteUsers right in the chat for own links and owner privileges for other links.
		 *
		 * <p> Returns {@link ChatInviteLinkMembers ChatInviteLinkMembers} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetChatInviteLinkMembers(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				byte[] inviteLinkTmp = new byte[input.readInt()];
				input.readFully(inviteLinkTmp);
				this.inviteLink = new String(inviteLinkTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (ChatInviteLinkMember.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.offsetMember = new ChatInviteLinkMember(input);
			}
			this.limit = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetChatInviteLinkMembers.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetChatInviteLinkMembers.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.inviteLink == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] inviteLinkTmp = this.inviteLink.getBytes(StandardCharsets.UTF_8);
				output.writeInt(inviteLinkTmp.length);
				output.write(inviteLinkTmp);
			}
			if (this.offsetMember == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.offsetMember.serialize(output);
			}
			output.writeInt(this.limit);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetChatInviteLinkMembers getChatInviteLinkMembers = (GetChatInviteLinkMembers) o;
			if (this.chatId != getChatInviteLinkMembers.chatId) {
				return false;
			}
			if (this.inviteLink != getChatInviteLinkMembers.inviteLink) {
				return false;
			}
			if (!Objects.equals(this.offsetMember, getChatInviteLinkMembers.offsetMember)) {
				return false;
			}
			if (this.limit != getChatInviteLinkMembers.limit) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.inviteLink == null ? 0 : this.inviteLink.hashCode());
			result = result * 31 + (this.offsetMember == null ? 0 : this.offsetMember.hashCode());
			return result;
		}
	}

	/**
	 * Returns invite links for a chat created by specified administrator.
	 * Requires administrator privileges and canInviteUsers right in the
	 * chat to get own links and owner privileges to get other links.
	 * <p> Returns {@link ChatInviteLinks ChatInviteLinks} </p>
	**/
	public static final class GetChatInviteLinks extends Function<ChatInviteLinks> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * User identifier of a chat administrator. Must be an identifier of the current user for non-owner.
		**/
		public long creatorUserId;

		/**
		 * Pass true if revoked links needs to be returned instead of active or expired.
		**/
		public boolean isRevoked;

		/**
		 * Creation date of an invite link starting after which to return invite links; use 0 to get results from the beginning.
		**/
		public int offsetDate;

		/**
		 * Invite link starting after which to return invite links; use empty string to get results from the beginning.
		**/
		public String offsetInviteLink;

		/**
		 * The maximum number of invite links to return; up to 100.
		**/
		public int limit;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 883252396;

		/**
		 * Returns invite links for a chat created by specified administrator. Requires administrator privileges and canInviteUsers right in the chat to get own links and owner privileges to get other links.
		 *
		 * <p> Returns {@link ChatInviteLinks ChatInviteLinks} </p>
		**/
		public GetChatInviteLinks() {}

		/**
		 * Returns invite links for a chat created by specified administrator. Requires administrator privileges and canInviteUsers right in the chat to get own links and owner privileges to get other links.
		 *
		 * <p> Returns {@link ChatInviteLinks ChatInviteLinks} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param creatorUserId User identifier of a chat administrator. Must be an identifier of the current user for non-owner.
		 * @param isRevoked Pass true if revoked links needs to be returned instead of active or expired.
		 * @param offsetDate Creation date of an invite link starting after which to return invite links; use 0 to get results from the beginning.
		 * @param offsetInviteLink Invite link starting after which to return invite links; use empty string to get results from the beginning.
		 * @param limit The maximum number of invite links to return; up to 100.
		 *
		 * <p> Returns {@link ChatInviteLinks ChatInviteLinks} </p>
		**/
		public GetChatInviteLinks(long chatId,
				long creatorUserId,
				boolean isRevoked,
				int offsetDate,
				String offsetInviteLink,
				int limit) {
			this.chatId = chatId;
			this.creatorUserId = creatorUserId;
			this.isRevoked = isRevoked;
			this.offsetDate = offsetDate;
			this.offsetInviteLink = offsetInviteLink;
			this.limit = limit;
		}

		/**
		 * Returns invite links for a chat created by specified administrator. Requires administrator privileges and canInviteUsers right in the chat to get own links and owner privileges to get other links.
		 *
		 * <p> Returns {@link ChatInviteLinks ChatInviteLinks} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetChatInviteLinks(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.creatorUserId = input.readLong();
			this.isRevoked = input.readBoolean();
			this.offsetDate = input.readInt();
			if (input.readBoolean()) {
				byte[] offsetInviteLinkTmp = new byte[input.readInt()];
				input.readFully(offsetInviteLinkTmp);
				this.offsetInviteLink = new String(offsetInviteLinkTmp, StandardCharsets.UTF_8);
			}
			this.limit = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetChatInviteLinks.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetChatInviteLinks.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.creatorUserId);
			output.writeBoolean(this.isRevoked);
			output.writeInt(this.offsetDate);
			if (this.offsetInviteLink == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] offsetInviteLinkTmp = this.offsetInviteLink.getBytes(StandardCharsets.UTF_8);
				output.writeInt(offsetInviteLinkTmp.length);
				output.write(offsetInviteLinkTmp);
			}
			output.writeInt(this.limit);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetChatInviteLinks getChatInviteLinks = (GetChatInviteLinks) o;
			if (this.chatId != getChatInviteLinks.chatId) {
				return false;
			}
			if (this.creatorUserId != getChatInviteLinks.creatorUserId) {
				return false;
			}
			if (this.isRevoked != getChatInviteLinks.isRevoked) {
				return false;
			}
			if (this.offsetDate != getChatInviteLinks.offsetDate) {
				return false;
			}
			if (this.offsetInviteLink != getChatInviteLinks.offsetInviteLink) {
				return false;
			}
			if (this.limit != getChatInviteLinks.limit) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.offsetInviteLink == null ? 0 : this.offsetInviteLink.hashCode());
			return result;
		}
	}

	/**
	 * Returns pending join requests in a chat.
	 * <p> Returns {@link ChatJoinRequests ChatJoinRequests} </p>
	**/
	public static final class GetChatJoinRequests extends Function<ChatJoinRequests> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Invite link for which to return join requests. If empty, all join requests will be returned. Requires administrator privileges and canInviteUsers right in the chat for own links and owner privileges for other links.
		**/
		public String inviteLink;

		/**
		 * A query to search for in the first names, last names and usernames of the users to return.
		**/
		public String query;

		/**
		 * A chat join request from which to return next requests; pass null to get results from the beginning.
		**/
		public ChatJoinRequest offsetRequest;

		/**
		 * The maximum number of requests to join the chat to return.
		**/
		public int limit;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -388428126;

		/**
		 * Returns pending join requests in a chat.
		 *
		 * <p> Returns {@link ChatJoinRequests ChatJoinRequests} </p>
		**/
		public GetChatJoinRequests() {}

		/**
		 * Returns pending join requests in a chat.
		 *
		 * <p> Returns {@link ChatJoinRequests ChatJoinRequests} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param inviteLink Invite link for which to return join requests. If empty, all join requests will be returned. Requires administrator privileges and canInviteUsers right in the chat for own links and owner privileges for other links.
		 * @param query A query to search for in the first names, last names and usernames of the users to return.
		 * @param offsetRequest A chat join request from which to return next requests; pass null to get results from the beginning.
		 * @param limit The maximum number of requests to join the chat to return.
		 *
		 * <p> Returns {@link ChatJoinRequests ChatJoinRequests} </p>
		**/
		public GetChatJoinRequests(long chatId,
				String inviteLink,
				String query,
				ChatJoinRequest offsetRequest,
				int limit) {
			this.chatId = chatId;
			this.inviteLink = inviteLink;
			this.query = query;
			this.offsetRequest = offsetRequest;
			this.limit = limit;
		}

		/**
		 * Returns pending join requests in a chat.
		 *
		 * <p> Returns {@link ChatJoinRequests ChatJoinRequests} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetChatJoinRequests(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				byte[] inviteLinkTmp = new byte[input.readInt()];
				input.readFully(inviteLinkTmp);
				this.inviteLink = new String(inviteLinkTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] queryTmp = new byte[input.readInt()];
				input.readFully(queryTmp);
				this.query = new String(queryTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (ChatJoinRequest.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.offsetRequest = new ChatJoinRequest(input);
			}
			this.limit = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetChatJoinRequests.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetChatJoinRequests.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.inviteLink == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] inviteLinkTmp = this.inviteLink.getBytes(StandardCharsets.UTF_8);
				output.writeInt(inviteLinkTmp.length);
				output.write(inviteLinkTmp);
			}
			if (this.query == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] queryTmp = this.query.getBytes(StandardCharsets.UTF_8);
				output.writeInt(queryTmp.length);
				output.write(queryTmp);
			}
			if (this.offsetRequest == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.offsetRequest.serialize(output);
			}
			output.writeInt(this.limit);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetChatJoinRequests getChatJoinRequests = (GetChatJoinRequests) o;
			if (this.chatId != getChatJoinRequests.chatId) {
				return false;
			}
			if (this.inviteLink != getChatJoinRequests.inviteLink) {
				return false;
			}
			if (this.query != getChatJoinRequests.query) {
				return false;
			}
			if (!Objects.equals(this.offsetRequest, getChatJoinRequests.offsetRequest)) {
				return false;
			}
			if (this.limit != getChatJoinRequests.limit) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.inviteLink == null ? 0 : this.inviteLink.hashCode());
			result = result * 31 + (this.query == null ? 0 : this.query.hashCode());
			result = result * 31 + (this.offsetRequest == null ? 0 : this.offsetRequest.hashCode());
			return result;
		}
	}

	/**
	 * Returns chat lists to which the chat can be added. This is an offline
	 * request.
	 * <p> Returns {@link ChatLists ChatLists} </p>
	**/
	public static final class GetChatListsToAddChat extends Function<ChatLists> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 654956193;

		/**
		 * Returns chat lists to which the chat can be added. This is an offline request.
		 *
		 * <p> Returns {@link ChatLists ChatLists} </p>
		**/
		public GetChatListsToAddChat() {}

		/**
		 * Returns chat lists to which the chat can be added. This is an offline request.
		 *
		 * <p> Returns {@link ChatLists ChatLists} </p>
		 *
		 * @param chatId Chat identifier.
		 *
		 * <p> Returns {@link ChatLists ChatLists} </p>
		**/
		public GetChatListsToAddChat(long chatId) {
			this.chatId = chatId;
		}

		/**
		 * Returns chat lists to which the chat can be added. This is an offline request.
		 *
		 * <p> Returns {@link ChatLists ChatLists} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetChatListsToAddChat(DataInput input) throws IOException {
			this.chatId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetChatListsToAddChat.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetChatListsToAddChat.CONSTRUCTOR);
			output.writeLong(this.chatId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetChatListsToAddChat getChatListsToAddChat = (GetChatListsToAddChat) o;
			if (this.chatId != getChatListsToAddChat.chatId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.chatId);
		}
	}

	/**
	 * Returns information about a single member of a chat.
	 * <p> Returns {@link ChatMember ChatMember} </p>
	**/
	public static final class GetChatMember extends Function<ChatMember> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Member identifier.
		**/
		public MessageSender memberId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -792636814;

		/**
		 * Returns information about a single member of a chat.
		 *
		 * <p> Returns {@link ChatMember ChatMember} </p>
		**/
		public GetChatMember() {}

		/**
		 * Returns information about a single member of a chat.
		 *
		 * <p> Returns {@link ChatMember ChatMember} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param memberId Member identifier.
		 *
		 * <p> Returns {@link ChatMember ChatMember} </p>
		**/
		public GetChatMember(long chatId, MessageSender memberId) {
			this.chatId = chatId;
			this.memberId = memberId;
		}

		/**
		 * Returns information about a single member of a chat.
		 *
		 * <p> Returns {@link ChatMember ChatMember} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetChatMember(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case MessageSenderUser.CONSTRUCTOR: this.memberId = new MessageSenderUser(input); break;
					case MessageSenderChat.CONSTRUCTOR: this.memberId = new MessageSenderChat(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetChatMember.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetChatMember.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.memberId == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.memberId.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetChatMember getChatMember = (GetChatMember) o;
			if (this.chatId != getChatMember.chatId) {
				return false;
			}
			if (!Objects.equals(this.memberId, getChatMember.memberId)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.memberId == null ? 0 : this.memberId.hashCode());
			return result;
		}
	}

	/**
	 * Returns the last message sent in a chat no later than the specified
	 * date.
	 * <p> Returns {@link Message Message} </p>
	**/
	public static final class GetChatMessageByDate extends Function<Message> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Point in time (Unix timestamp) relative to which to search for messages.
		**/
		public int date;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1062564150;

		/**
		 * Returns the last message sent in a chat no later than the specified date.
		 *
		 * <p> Returns {@link Message Message} </p>
		**/
		public GetChatMessageByDate() {}

		/**
		 * Returns the last message sent in a chat no later than the specified date.
		 *
		 * <p> Returns {@link Message Message} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param date Point in time (Unix timestamp) relative to which to search for messages.
		 *
		 * <p> Returns {@link Message Message} </p>
		**/
		public GetChatMessageByDate(long chatId, int date) {
			this.chatId = chatId;
			this.date = date;
		}

		/**
		 * Returns the last message sent in a chat no later than the specified date.
		 *
		 * <p> Returns {@link Message Message} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetChatMessageByDate(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.date = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetChatMessageByDate.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetChatMessageByDate.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeInt(this.date);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetChatMessageByDate getChatMessageByDate = (GetChatMessageByDate) o;
			if (this.chatId != getChatMessageByDate.chatId) {
				return false;
			}
			if (this.date != getChatMessageByDate.date) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Returns information about the next messages of the specified type in
	 * the chat split by days. Returns the results in reverse chronological
	 * order. Can return partial result for the last returned day. Behavior
	 * of this method depends on the value of the option
	 * &quot;utc_time_offset&quot;.
	 * <p> Returns {@link MessageCalendar MessageCalendar} </p>
	**/
	public static final class GetChatMessageCalendar extends Function<MessageCalendar> {


		/**
		 * Identifier of the chat in which to return information about messages.
		**/
		public long chatId;

		/**
		 * Filter for message content. Filters searchMessagesFilterEmpty, searchMessagesFilterMention, searchMessagesFilterUnreadMention, and searchMessagesFilterUnreadReaction are unsupported in this function.
		**/
		public SearchMessagesFilter filter;

		/**
		 * The message identifier from which to return information about messages; use 0 to get results from the last message.
		**/
		public long fromMessageId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -326164204;

		/**
		 * Returns information about the next messages of the specified type in the chat split by days. Returns the results in reverse chronological order. Can return partial result for the last returned day. Behavior of this method depends on the value of the option &quot;utc_time_offset&quot;.
		 *
		 * <p> Returns {@link MessageCalendar MessageCalendar} </p>
		**/
		public GetChatMessageCalendar() {}

		/**
		 * Returns information about the next messages of the specified type in the chat split by days. Returns the results in reverse chronological order. Can return partial result for the last returned day. Behavior of this method depends on the value of the option &quot;utc_time_offset&quot;.
		 *
		 * <p> Returns {@link MessageCalendar MessageCalendar} </p>
		 *
		 * @param chatId Identifier of the chat in which to return information about messages.
		 * @param filter Filter for message content. Filters searchMessagesFilterEmpty, searchMessagesFilterMention, searchMessagesFilterUnreadMention, and searchMessagesFilterUnreadReaction are unsupported in this function.
		 * @param fromMessageId The message identifier from which to return information about messages; use 0 to get results from the last message.
		 *
		 * <p> Returns {@link MessageCalendar MessageCalendar} </p>
		**/
		public GetChatMessageCalendar(long chatId, SearchMessagesFilter filter, long fromMessageId) {
			this.chatId = chatId;
			this.filter = filter;
			this.fromMessageId = fromMessageId;
		}

		/**
		 * Returns information about the next messages of the specified type in the chat split by days. Returns the results in reverse chronological order. Can return partial result for the last returned day. Behavior of this method depends on the value of the option &quot;utc_time_offset&quot;.
		 *
		 * <p> Returns {@link MessageCalendar MessageCalendar} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetChatMessageCalendar(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case SearchMessagesFilterEmpty.CONSTRUCTOR: this.filter = new SearchMessagesFilterEmpty(input); break;
					case SearchMessagesFilterAnimation.CONSTRUCTOR: this.filter = new SearchMessagesFilterAnimation(input); break;
					case SearchMessagesFilterAudio.CONSTRUCTOR: this.filter = new SearchMessagesFilterAudio(input); break;
					case SearchMessagesFilterDocument.CONSTRUCTOR: this.filter = new SearchMessagesFilterDocument(input); break;
					case SearchMessagesFilterPhoto.CONSTRUCTOR: this.filter = new SearchMessagesFilterPhoto(input); break;
					case SearchMessagesFilterVideo.CONSTRUCTOR: this.filter = new SearchMessagesFilterVideo(input); break;
					case SearchMessagesFilterVoiceNote.CONSTRUCTOR: this.filter = new SearchMessagesFilterVoiceNote(input); break;
					case SearchMessagesFilterPhotoAndVideo.CONSTRUCTOR: this.filter = new SearchMessagesFilterPhotoAndVideo(input); break;
					case SearchMessagesFilterUrl.CONSTRUCTOR: this.filter = new SearchMessagesFilterUrl(input); break;
					case SearchMessagesFilterChatPhoto.CONSTRUCTOR: this.filter = new SearchMessagesFilterChatPhoto(input); break;
					case SearchMessagesFilterVideoNote.CONSTRUCTOR: this.filter = new SearchMessagesFilterVideoNote(input); break;
					case SearchMessagesFilterVoiceAndVideoNote.CONSTRUCTOR: this.filter = new SearchMessagesFilterVoiceAndVideoNote(input); break;
					case SearchMessagesFilterMention.CONSTRUCTOR: this.filter = new SearchMessagesFilterMention(input); break;
					case SearchMessagesFilterUnreadMention.CONSTRUCTOR: this.filter = new SearchMessagesFilterUnreadMention(input); break;
					case SearchMessagesFilterUnreadReaction.CONSTRUCTOR: this.filter = new SearchMessagesFilterUnreadReaction(input); break;
					case SearchMessagesFilterFailedToSend.CONSTRUCTOR: this.filter = new SearchMessagesFilterFailedToSend(input); break;
					case SearchMessagesFilterPinned.CONSTRUCTOR: this.filter = new SearchMessagesFilterPinned(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.fromMessageId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetChatMessageCalendar.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetChatMessageCalendar.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.filter == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.filter.serialize(output);
			}
			output.writeLong(this.fromMessageId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetChatMessageCalendar getChatMessageCalendar = (GetChatMessageCalendar) o;
			if (this.chatId != getChatMessageCalendar.chatId) {
				return false;
			}
			if (!Objects.equals(this.filter, getChatMessageCalendar.filter)) {
				return false;
			}
			if (this.fromMessageId != getChatMessageCalendar.fromMessageId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.filter == null ? 0 : this.filter.hashCode());
			return result;
		}
	}

	/**
	 * Returns approximate number of messages of the specified type in the
	 * chat.
	 * <p> Returns {@link Count Count} </p>
	**/
	public static final class GetChatMessageCount extends Function<Count> {


		/**
		 * Identifier of the chat in which to count messages.
		**/
		public long chatId;

		/**
		 * Filter for message content; searchMessagesFilterEmpty is unsupported in this function.
		**/
		public SearchMessagesFilter filter;

		/**
		 * Pass true to get the number of messages without sending network requests, or -1 if the number of messages is unknown locally.
		**/
		public boolean returnLocal;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 205435308;

		/**
		 * Returns approximate number of messages of the specified type in the chat.
		 *
		 * <p> Returns {@link Count Count} </p>
		**/
		public GetChatMessageCount() {}

		/**
		 * Returns approximate number of messages of the specified type in the chat.
		 *
		 * <p> Returns {@link Count Count} </p>
		 *
		 * @param chatId Identifier of the chat in which to count messages.
		 * @param filter Filter for message content; searchMessagesFilterEmpty is unsupported in this function.
		 * @param returnLocal Pass true to get the number of messages without sending network requests, or -1 if the number of messages is unknown locally.
		 *
		 * <p> Returns {@link Count Count} </p>
		**/
		public GetChatMessageCount(long chatId,
				SearchMessagesFilter filter,
				boolean returnLocal) {
			this.chatId = chatId;
			this.filter = filter;
			this.returnLocal = returnLocal;
		}

		/**
		 * Returns approximate number of messages of the specified type in the chat.
		 *
		 * <p> Returns {@link Count Count} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetChatMessageCount(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case SearchMessagesFilterEmpty.CONSTRUCTOR: this.filter = new SearchMessagesFilterEmpty(input); break;
					case SearchMessagesFilterAnimation.CONSTRUCTOR: this.filter = new SearchMessagesFilterAnimation(input); break;
					case SearchMessagesFilterAudio.CONSTRUCTOR: this.filter = new SearchMessagesFilterAudio(input); break;
					case SearchMessagesFilterDocument.CONSTRUCTOR: this.filter = new SearchMessagesFilterDocument(input); break;
					case SearchMessagesFilterPhoto.CONSTRUCTOR: this.filter = new SearchMessagesFilterPhoto(input); break;
					case SearchMessagesFilterVideo.CONSTRUCTOR: this.filter = new SearchMessagesFilterVideo(input); break;
					case SearchMessagesFilterVoiceNote.CONSTRUCTOR: this.filter = new SearchMessagesFilterVoiceNote(input); break;
					case SearchMessagesFilterPhotoAndVideo.CONSTRUCTOR: this.filter = new SearchMessagesFilterPhotoAndVideo(input); break;
					case SearchMessagesFilterUrl.CONSTRUCTOR: this.filter = new SearchMessagesFilterUrl(input); break;
					case SearchMessagesFilterChatPhoto.CONSTRUCTOR: this.filter = new SearchMessagesFilterChatPhoto(input); break;
					case SearchMessagesFilterVideoNote.CONSTRUCTOR: this.filter = new SearchMessagesFilterVideoNote(input); break;
					case SearchMessagesFilterVoiceAndVideoNote.CONSTRUCTOR: this.filter = new SearchMessagesFilterVoiceAndVideoNote(input); break;
					case SearchMessagesFilterMention.CONSTRUCTOR: this.filter = new SearchMessagesFilterMention(input); break;
					case SearchMessagesFilterUnreadMention.CONSTRUCTOR: this.filter = new SearchMessagesFilterUnreadMention(input); break;
					case SearchMessagesFilterUnreadReaction.CONSTRUCTOR: this.filter = new SearchMessagesFilterUnreadReaction(input); break;
					case SearchMessagesFilterFailedToSend.CONSTRUCTOR: this.filter = new SearchMessagesFilterFailedToSend(input); break;
					case SearchMessagesFilterPinned.CONSTRUCTOR: this.filter = new SearchMessagesFilterPinned(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.returnLocal = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetChatMessageCount.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetChatMessageCount.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.filter == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.filter.serialize(output);
			}
			output.writeBoolean(this.returnLocal);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetChatMessageCount getChatMessageCount = (GetChatMessageCount) o;
			if (this.chatId != getChatMessageCount.chatId) {
				return false;
			}
			if (!Objects.equals(this.filter, getChatMessageCount.filter)) {
				return false;
			}
			if (this.returnLocal != getChatMessageCount.returnLocal) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.filter == null ? 0 : this.filter.hashCode());
			return result;
		}
	}

	/**
	 * Returns approximate 1-based position of a message among messages,
	 * which can be found by the specified filter in the chat. Cannot be
	 * used in secret chats.
	 * <p> Returns {@link Count Count} </p>
	**/
	public static final class GetChatMessagePosition extends Function<Count> {


		/**
		 * Identifier of the chat in which to find message position.
		**/
		public long chatId;

		/**
		 * Message identifier.
		**/
		public long messageId;

		/**
		 * Filter for message content; searchMessagesFilterEmpty, searchMessagesFilterUnreadMention, searchMessagesFilterUnreadReaction, and searchMessagesFilterFailedToSend are unsupported in this function.
		**/
		public SearchMessagesFilter filter;

		/**
		 * If not 0, only messages in the specified thread will be considered; supergroups only.
		**/
		public long messageThreadId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -559474920;

		/**
		 * Returns approximate 1-based position of a message among messages, which can be found by the specified filter in the chat. Cannot be used in secret chats.
		 *
		 * <p> Returns {@link Count Count} </p>
		**/
		public GetChatMessagePosition() {}

		/**
		 * Returns approximate 1-based position of a message among messages, which can be found by the specified filter in the chat. Cannot be used in secret chats.
		 *
		 * <p> Returns {@link Count Count} </p>
		 *
		 * @param chatId Identifier of the chat in which to find message position.
		 * @param messageId Message identifier.
		 * @param filter Filter for message content; searchMessagesFilterEmpty, searchMessagesFilterUnreadMention, searchMessagesFilterUnreadReaction, and searchMessagesFilterFailedToSend are unsupported in this function.
		 * @param messageThreadId If not 0, only messages in the specified thread will be considered; supergroups only.
		 *
		 * <p> Returns {@link Count Count} </p>
		**/
		public GetChatMessagePosition(long chatId,
				long messageId,
				SearchMessagesFilter filter,
				long messageThreadId) {
			this.chatId = chatId;
			this.messageId = messageId;
			this.filter = filter;
			this.messageThreadId = messageThreadId;
		}

		/**
		 * Returns approximate 1-based position of a message among messages, which can be found by the specified filter in the chat. Cannot be used in secret chats.
		 *
		 * <p> Returns {@link Count Count} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetChatMessagePosition(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case SearchMessagesFilterEmpty.CONSTRUCTOR: this.filter = new SearchMessagesFilterEmpty(input); break;
					case SearchMessagesFilterAnimation.CONSTRUCTOR: this.filter = new SearchMessagesFilterAnimation(input); break;
					case SearchMessagesFilterAudio.CONSTRUCTOR: this.filter = new SearchMessagesFilterAudio(input); break;
					case SearchMessagesFilterDocument.CONSTRUCTOR: this.filter = new SearchMessagesFilterDocument(input); break;
					case SearchMessagesFilterPhoto.CONSTRUCTOR: this.filter = new SearchMessagesFilterPhoto(input); break;
					case SearchMessagesFilterVideo.CONSTRUCTOR: this.filter = new SearchMessagesFilterVideo(input); break;
					case SearchMessagesFilterVoiceNote.CONSTRUCTOR: this.filter = new SearchMessagesFilterVoiceNote(input); break;
					case SearchMessagesFilterPhotoAndVideo.CONSTRUCTOR: this.filter = new SearchMessagesFilterPhotoAndVideo(input); break;
					case SearchMessagesFilterUrl.CONSTRUCTOR: this.filter = new SearchMessagesFilterUrl(input); break;
					case SearchMessagesFilterChatPhoto.CONSTRUCTOR: this.filter = new SearchMessagesFilterChatPhoto(input); break;
					case SearchMessagesFilterVideoNote.CONSTRUCTOR: this.filter = new SearchMessagesFilterVideoNote(input); break;
					case SearchMessagesFilterVoiceAndVideoNote.CONSTRUCTOR: this.filter = new SearchMessagesFilterVoiceAndVideoNote(input); break;
					case SearchMessagesFilterMention.CONSTRUCTOR: this.filter = new SearchMessagesFilterMention(input); break;
					case SearchMessagesFilterUnreadMention.CONSTRUCTOR: this.filter = new SearchMessagesFilterUnreadMention(input); break;
					case SearchMessagesFilterUnreadReaction.CONSTRUCTOR: this.filter = new SearchMessagesFilterUnreadReaction(input); break;
					case SearchMessagesFilterFailedToSend.CONSTRUCTOR: this.filter = new SearchMessagesFilterFailedToSend(input); break;
					case SearchMessagesFilterPinned.CONSTRUCTOR: this.filter = new SearchMessagesFilterPinned(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.messageThreadId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetChatMessagePosition.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetChatMessagePosition.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
			if (this.filter == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.filter.serialize(output);
			}
			output.writeLong(this.messageThreadId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetChatMessagePosition getChatMessagePosition = (GetChatMessagePosition) o;
			if (this.chatId != getChatMessagePosition.chatId) {
				return false;
			}
			if (this.messageId != getChatMessagePosition.messageId) {
				return false;
			}
			if (!Objects.equals(this.filter, getChatMessagePosition.filter)) {
				return false;
			}
			if (this.messageThreadId != getChatMessagePosition.messageThreadId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.filter == null ? 0 : this.filter.hashCode());
			return result;
		}
	}

	/**
	 * Returns list of chats with non-default notification settings.
	 * <p> Returns {@link Chats Chats} </p>
	**/
	public static final class GetChatNotificationSettingsExceptions extends Function<Chats> {


		/**
		 * If specified, only chats from the scope will be returned; pass null to return chats from all scopes.
		**/
		public NotificationSettingsScope scope;

		/**
		 * Pass true to include in the response chats with only non-default sound.
		**/
		public boolean compareSound;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 201199121;

		/**
		 * Returns list of chats with non-default notification settings.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		**/
		public GetChatNotificationSettingsExceptions() {}

		/**
		 * Returns list of chats with non-default notification settings.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		 *
		 * @param scope If specified, only chats from the scope will be returned; pass null to return chats from all scopes.
		 * @param compareSound Pass true to include in the response chats with only non-default sound.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		**/
		public GetChatNotificationSettingsExceptions(NotificationSettingsScope scope, boolean compareSound) {
			this.scope = scope;
			this.compareSound = compareSound;
		}

		/**
		 * Returns list of chats with non-default notification settings.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetChatNotificationSettingsExceptions(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case NotificationSettingsScopePrivateChats.CONSTRUCTOR: this.scope = new NotificationSettingsScopePrivateChats(input); break;
					case NotificationSettingsScopeGroupChats.CONSTRUCTOR: this.scope = new NotificationSettingsScopeGroupChats(input); break;
					case NotificationSettingsScopeChannelChats.CONSTRUCTOR: this.scope = new NotificationSettingsScopeChannelChats(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.compareSound = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetChatNotificationSettingsExceptions.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetChatNotificationSettingsExceptions.CONSTRUCTOR);
			if (this.scope == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.scope.serialize(output);
			}
			output.writeBoolean(this.compareSound);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetChatNotificationSettingsExceptions getChatNotificationSettingsExceptions = (GetChatNotificationSettingsExceptions) o;
			if (!Objects.equals(this.scope, getChatNotificationSettingsExceptions.scope)) {
				return false;
			}
			if (this.compareSound != getChatNotificationSettingsExceptions.compareSound) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.compareSound);
			result = result * 31 + (this.scope == null ? 0 : this.scope.hashCode());
			return result;
		}
	}

	/**
	 * Returns information about a newest pinned message in the chat.
	 * <p> Returns {@link Message Message} </p>
	**/
	public static final class GetChatPinnedMessage extends Function<Message> {


		/**
		 * Identifier of the chat the message belongs to.
		**/
		public long chatId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 359865008;

		/**
		 * Returns information about a newest pinned message in the chat.
		 *
		 * <p> Returns {@link Message Message} </p>
		**/
		public GetChatPinnedMessage() {}

		/**
		 * Returns information about a newest pinned message in the chat.
		 *
		 * <p> Returns {@link Message Message} </p>
		 *
		 * @param chatId Identifier of the chat the message belongs to.
		 *
		 * <p> Returns {@link Message Message} </p>
		**/
		public GetChatPinnedMessage(long chatId) {
			this.chatId = chatId;
		}

		/**
		 * Returns information about a newest pinned message in the chat.
		 *
		 * <p> Returns {@link Message Message} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetChatPinnedMessage(DataInput input) throws IOException {
			this.chatId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetChatPinnedMessage.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetChatPinnedMessage.CONSTRUCTOR);
			output.writeLong(this.chatId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetChatPinnedMessage getChatPinnedMessage = (GetChatPinnedMessage) o;
			if (this.chatId != getChatPinnedMessage.chatId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.chatId);
		}
	}

	/**
	 * Returns all scheduled messages in a chat. The messages are returned
	 * in a reverse chronological order (i.e., in order of decreasing
	 * messageId).
	 * <p> Returns {@link Messages Messages} </p>
	**/
	public static final class GetChatScheduledMessages extends Function<Messages> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -549638149;

		/**
		 * Returns all scheduled messages in a chat. The messages are returned in a reverse chronological order (i.e., in order of decreasing messageId).
		 *
		 * <p> Returns {@link Messages Messages} </p>
		**/
		public GetChatScheduledMessages() {}

		/**
		 * Returns all scheduled messages in a chat. The messages are returned in a reverse chronological order (i.e., in order of decreasing messageId).
		 *
		 * <p> Returns {@link Messages Messages} </p>
		 *
		 * @param chatId Chat identifier.
		 *
		 * <p> Returns {@link Messages Messages} </p>
		**/
		public GetChatScheduledMessages(long chatId) {
			this.chatId = chatId;
		}

		/**
		 * Returns all scheduled messages in a chat. The messages are returned in a reverse chronological order (i.e., in order of decreasing messageId).
		 *
		 * <p> Returns {@link Messages Messages} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetChatScheduledMessages(DataInput input) throws IOException {
			this.chatId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetChatScheduledMessages.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetChatScheduledMessages.CONSTRUCTOR);
			output.writeLong(this.chatId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetChatScheduledMessages getChatScheduledMessages = (GetChatScheduledMessages) o;
			if (this.chatId != getChatScheduledMessages.chatId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.chatId);
		}
	}

	/**
	 * Returns sparse positions of messages of the specified type in the
	 * chat to be used for shared media scroll implementation. Returns the
	 * results in reverse chronological order (i.e., in order of decreasing
	 * messageId). Cannot be used in secret chats or with
	 * searchMessagesFilterFailedToSend filter without an enabled message
	 * database.
	 * <p> Returns {@link MessagePositions MessagePositions} </p>
	**/
	public static final class GetChatSparseMessagePositions extends Function<MessagePositions> {


		/**
		 * Identifier of the chat in which to return information about message positions.
		**/
		public long chatId;

		/**
		 * Filter for message content. Filters searchMessagesFilterEmpty, searchMessagesFilterMention, searchMessagesFilterUnreadMention, and searchMessagesFilterUnreadReaction are unsupported in this function.
		**/
		public SearchMessagesFilter filter;

		/**
		 * The message identifier from which to return information about message positions.
		**/
		public long fromMessageId;

		/**
		 * The expected number of message positions to be returned; 50-2000. A smaller number of positions can be returned, if there are not enough appropriate messages.
		**/
		public int limit;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -462227580;

		/**
		 * Returns sparse positions of messages of the specified type in the chat to be used for shared media scroll implementation. Returns the results in reverse chronological order (i.e., in order of decreasing messageId). Cannot be used in secret chats or with searchMessagesFilterFailedToSend filter without an enabled message database.
		 *
		 * <p> Returns {@link MessagePositions MessagePositions} </p>
		**/
		public GetChatSparseMessagePositions() {}

		/**
		 * Returns sparse positions of messages of the specified type in the chat to be used for shared media scroll implementation. Returns the results in reverse chronological order (i.e., in order of decreasing messageId). Cannot be used in secret chats or with searchMessagesFilterFailedToSend filter without an enabled message database.
		 *
		 * <p> Returns {@link MessagePositions MessagePositions} </p>
		 *
		 * @param chatId Identifier of the chat in which to return information about message positions.
		 * @param filter Filter for message content. Filters searchMessagesFilterEmpty, searchMessagesFilterMention, searchMessagesFilterUnreadMention, and searchMessagesFilterUnreadReaction are unsupported in this function.
		 * @param fromMessageId The message identifier from which to return information about message positions.
		 * @param limit The expected number of message positions to be returned; 50-2000. A smaller number of positions can be returned, if there are not enough appropriate messages.
		 *
		 * <p> Returns {@link MessagePositions MessagePositions} </p>
		**/
		public GetChatSparseMessagePositions(long chatId,
				SearchMessagesFilter filter,
				long fromMessageId,
				int limit) {
			this.chatId = chatId;
			this.filter = filter;
			this.fromMessageId = fromMessageId;
			this.limit = limit;
		}

		/**
		 * Returns sparse positions of messages of the specified type in the chat to be used for shared media scroll implementation. Returns the results in reverse chronological order (i.e., in order of decreasing messageId). Cannot be used in secret chats or with searchMessagesFilterFailedToSend filter without an enabled message database.
		 *
		 * <p> Returns {@link MessagePositions MessagePositions} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetChatSparseMessagePositions(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case SearchMessagesFilterEmpty.CONSTRUCTOR: this.filter = new SearchMessagesFilterEmpty(input); break;
					case SearchMessagesFilterAnimation.CONSTRUCTOR: this.filter = new SearchMessagesFilterAnimation(input); break;
					case SearchMessagesFilterAudio.CONSTRUCTOR: this.filter = new SearchMessagesFilterAudio(input); break;
					case SearchMessagesFilterDocument.CONSTRUCTOR: this.filter = new SearchMessagesFilterDocument(input); break;
					case SearchMessagesFilterPhoto.CONSTRUCTOR: this.filter = new SearchMessagesFilterPhoto(input); break;
					case SearchMessagesFilterVideo.CONSTRUCTOR: this.filter = new SearchMessagesFilterVideo(input); break;
					case SearchMessagesFilterVoiceNote.CONSTRUCTOR: this.filter = new SearchMessagesFilterVoiceNote(input); break;
					case SearchMessagesFilterPhotoAndVideo.CONSTRUCTOR: this.filter = new SearchMessagesFilterPhotoAndVideo(input); break;
					case SearchMessagesFilterUrl.CONSTRUCTOR: this.filter = new SearchMessagesFilterUrl(input); break;
					case SearchMessagesFilterChatPhoto.CONSTRUCTOR: this.filter = new SearchMessagesFilterChatPhoto(input); break;
					case SearchMessagesFilterVideoNote.CONSTRUCTOR: this.filter = new SearchMessagesFilterVideoNote(input); break;
					case SearchMessagesFilterVoiceAndVideoNote.CONSTRUCTOR: this.filter = new SearchMessagesFilterVoiceAndVideoNote(input); break;
					case SearchMessagesFilterMention.CONSTRUCTOR: this.filter = new SearchMessagesFilterMention(input); break;
					case SearchMessagesFilterUnreadMention.CONSTRUCTOR: this.filter = new SearchMessagesFilterUnreadMention(input); break;
					case SearchMessagesFilterUnreadReaction.CONSTRUCTOR: this.filter = new SearchMessagesFilterUnreadReaction(input); break;
					case SearchMessagesFilterFailedToSend.CONSTRUCTOR: this.filter = new SearchMessagesFilterFailedToSend(input); break;
					case SearchMessagesFilterPinned.CONSTRUCTOR: this.filter = new SearchMessagesFilterPinned(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.fromMessageId = input.readLong();
			this.limit = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetChatSparseMessagePositions.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetChatSparseMessagePositions.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.filter == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.filter.serialize(output);
			}
			output.writeLong(this.fromMessageId);
			output.writeInt(this.limit);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetChatSparseMessagePositions getChatSparseMessagePositions = (GetChatSparseMessagePositions) o;
			if (this.chatId != getChatSparseMessagePositions.chatId) {
				return false;
			}
			if (!Objects.equals(this.filter, getChatSparseMessagePositions.filter)) {
				return false;
			}
			if (this.fromMessageId != getChatSparseMessagePositions.fromMessageId) {
				return false;
			}
			if (this.limit != getChatSparseMessagePositions.limit) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.filter == null ? 0 : this.filter.hashCode());
			return result;
		}
	}

	/**
	 * Returns sponsored messages to be shown in a chat; for channel chats
	 * only.
	 * <p> Returns {@link SponsoredMessages SponsoredMessages} </p>
	**/
	public static final class GetChatSponsoredMessages extends Function<SponsoredMessages> {


		/**
		 * Identifier of the chat.
		**/
		public long chatId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1353203864;

		/**
		 * Returns sponsored messages to be shown in a chat; for channel chats only.
		 *
		 * <p> Returns {@link SponsoredMessages SponsoredMessages} </p>
		**/
		public GetChatSponsoredMessages() {}

		/**
		 * Returns sponsored messages to be shown in a chat; for channel chats only.
		 *
		 * <p> Returns {@link SponsoredMessages SponsoredMessages} </p>
		 *
		 * @param chatId Identifier of the chat.
		 *
		 * <p> Returns {@link SponsoredMessages SponsoredMessages} </p>
		**/
		public GetChatSponsoredMessages(long chatId) {
			this.chatId = chatId;
		}

		/**
		 * Returns sponsored messages to be shown in a chat; for channel chats only.
		 *
		 * <p> Returns {@link SponsoredMessages SponsoredMessages} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetChatSponsoredMessages(DataInput input) throws IOException {
			this.chatId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetChatSponsoredMessages.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetChatSponsoredMessages.CONSTRUCTOR);
			output.writeLong(this.chatId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetChatSponsoredMessages getChatSponsoredMessages = (GetChatSponsoredMessages) o;
			if (this.chatId != getChatSponsoredMessages.chatId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.chatId);
		}
	}

	/**
	 * Returns detailed statistics about a chat. Currently, this method can
	 * be used only for supergroups and channels. Can be used only if
	 * supergroupFullInfo.canGetStatistics == true.
	 * <p> Returns {@link ChatStatistics ChatStatistics} </p>
	**/
	public static final class GetChatStatistics extends Function<ChatStatistics> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Pass true if a dark theme is used by the application.
		**/
		public boolean isDark;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 327057816;

		/**
		 * Returns detailed statistics about a chat. Currently, this method can be used only for supergroups and channels. Can be used only if supergroupFullInfo.canGetStatistics == true.
		 *
		 * <p> Returns {@link ChatStatistics ChatStatistics} </p>
		**/
		public GetChatStatistics() {}

		/**
		 * Returns detailed statistics about a chat. Currently, this method can be used only for supergroups and channels. Can be used only if supergroupFullInfo.canGetStatistics == true.
		 *
		 * <p> Returns {@link ChatStatistics ChatStatistics} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param isDark Pass true if a dark theme is used by the application.
		 *
		 * <p> Returns {@link ChatStatistics ChatStatistics} </p>
		**/
		public GetChatStatistics(long chatId, boolean isDark) {
			this.chatId = chatId;
			this.isDark = isDark;
		}

		/**
		 * Returns detailed statistics about a chat. Currently, this method can be used only for supergroups and channels. Can be used only if supergroupFullInfo.canGetStatistics == true.
		 *
		 * <p> Returns {@link ChatStatistics ChatStatistics} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetChatStatistics(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.isDark = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetChatStatistics.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetChatStatistics.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeBoolean(this.isDark);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetChatStatistics getChatStatistics = (GetChatStatistics) o;
			if (this.chatId != getChatStatistics.chatId) {
				return false;
			}
			if (this.isDark != getChatStatistics.isDark) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Returns an ordered list of chats from the beginning of a chat list.
	 * For informational purposes only. Use loadChats and updates processing
	 * instead to maintain chat lists in a consistent state.
	 * <p> Returns {@link Chats Chats} </p>
	**/
	public static final class GetChats extends Function<Chats> {


		/**
		 * The chat list in which to return chats; pass null to get chats from the main chat list.
		**/
		public ChatList chatList;

		/**
		 * The maximum number of chats to be returned.
		**/
		public int limit;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -972768574;

		/**
		 * Returns an ordered list of chats from the beginning of a chat list. For informational purposes only. Use loadChats and updates processing instead to maintain chat lists in a consistent state.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		**/
		public GetChats() {}

		/**
		 * Returns an ordered list of chats from the beginning of a chat list. For informational purposes only. Use loadChats and updates processing instead to maintain chat lists in a consistent state.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		 *
		 * @param chatList The chat list in which to return chats; pass null to get chats from the main chat list.
		 * @param limit The maximum number of chats to be returned.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		**/
		public GetChats(ChatList chatList, int limit) {
			this.chatList = chatList;
			this.limit = limit;
		}

		/**
		 * Returns an ordered list of chats from the beginning of a chat list. For informational purposes only. Use loadChats and updates processing instead to maintain chat lists in a consistent state.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetChats(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ChatListMain.CONSTRUCTOR: this.chatList = new ChatListMain(input); break;
					case ChatListArchive.CONSTRUCTOR: this.chatList = new ChatListArchive(input); break;
					case ChatListFolder.CONSTRUCTOR: this.chatList = new ChatListFolder(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.limit = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetChats.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetChats.CONSTRUCTOR);
			if (this.chatList == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.chatList.serialize(output);
			}
			output.writeInt(this.limit);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetChats getChats = (GetChats) o;
			if (!Objects.equals(this.chatList, getChats.chatList)) {
				return false;
			}
			if (this.limit != getChats.limit) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.limit);
			result = result * 31 + (this.chatList == null ? 0 : this.chatList.hashCode());
			return result;
		}
	}

	/**
	 * Returns identifiers of chats from a chat folder, suitable for adding
	 * to a chat folder invite link.
	 * <p> Returns {@link Chats Chats} </p>
	**/
	public static final class GetChatsForChatFolderInviteLink extends Function<Chats> {


		/**
		 * Chat folder identifier.
		**/
		public int chatFolderId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1873561929;

		/**
		 * Returns identifiers of chats from a chat folder, suitable for adding to a chat folder invite link.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		**/
		public GetChatsForChatFolderInviteLink() {}

		/**
		 * Returns identifiers of chats from a chat folder, suitable for adding to a chat folder invite link.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		 *
		 * @param chatFolderId Chat folder identifier.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		**/
		public GetChatsForChatFolderInviteLink(int chatFolderId) {
			this.chatFolderId = chatFolderId;
		}

		/**
		 * Returns identifiers of chats from a chat folder, suitable for adding to a chat folder invite link.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetChatsForChatFolderInviteLink(DataInput input) throws IOException {
			this.chatFolderId = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetChatsForChatFolderInviteLink.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetChatsForChatFolderInviteLink.CONSTRUCTOR);
			output.writeInt(this.chatFolderId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetChatsForChatFolderInviteLink getChatsForChatFolderInviteLink = (GetChatsForChatFolderInviteLink) o;
			if (this.chatFolderId != getChatsForChatFolderInviteLink.chatFolderId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.chatFolderId);
		}
	}

	/**
	 * Returns list of commands supported by the bot for the given user
	 * scope and language; for bots only.
	 * <p> Returns {@link BotCommands BotCommands} </p>
	**/
	public static final class GetCommands extends Function<BotCommands> {


		/**
		 * The scope to which the commands are relevant; pass null to get commands in the default bot command scope.
		**/
		public BotCommandScope scope;

		/**
		 * A two-letter ISO 639-1 language code or an empty string.
		**/
		public String languageCode;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1488621559;

		/**
		 * Returns list of commands supported by the bot for the given user scope and language; for bots only.
		 *
		 * <p> Returns {@link BotCommands BotCommands} </p>
		**/
		public GetCommands() {}

		/**
		 * Returns list of commands supported by the bot for the given user scope and language; for bots only.
		 *
		 * <p> Returns {@link BotCommands BotCommands} </p>
		 *
		 * @param scope The scope to which the commands are relevant; pass null to get commands in the default bot command scope.
		 * @param languageCode A two-letter ISO 639-1 language code or an empty string.
		 *
		 * <p> Returns {@link BotCommands BotCommands} </p>
		**/
		public GetCommands(BotCommandScope scope, String languageCode) {
			this.scope = scope;
			this.languageCode = languageCode;
		}

		/**
		 * Returns list of commands supported by the bot for the given user scope and language; for bots only.
		 *
		 * <p> Returns {@link BotCommands BotCommands} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetCommands(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case BotCommandScopeDefault.CONSTRUCTOR: this.scope = new BotCommandScopeDefault(input); break;
					case BotCommandScopeAllPrivateChats.CONSTRUCTOR: this.scope = new BotCommandScopeAllPrivateChats(input); break;
					case BotCommandScopeAllGroupChats.CONSTRUCTOR: this.scope = new BotCommandScopeAllGroupChats(input); break;
					case BotCommandScopeAllChatAdministrators.CONSTRUCTOR: this.scope = new BotCommandScopeAllChatAdministrators(input); break;
					case BotCommandScopeChat.CONSTRUCTOR: this.scope = new BotCommandScopeChat(input); break;
					case BotCommandScopeChatAdministrators.CONSTRUCTOR: this.scope = new BotCommandScopeChatAdministrators(input); break;
					case BotCommandScopeChatMember.CONSTRUCTOR: this.scope = new BotCommandScopeChatMember(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				byte[] languageCodeTmp = new byte[input.readInt()];
				input.readFully(languageCodeTmp);
				this.languageCode = new String(languageCodeTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetCommands.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetCommands.CONSTRUCTOR);
			if (this.scope == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.scope.serialize(output);
			}
			if (this.languageCode == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] languageCodeTmp = this.languageCode.getBytes(StandardCharsets.UTF_8);
				output.writeInt(languageCodeTmp.length);
				output.write(languageCodeTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetCommands getCommands = (GetCommands) o;
			if (!Objects.equals(this.scope, getCommands.scope)) {
				return false;
			}
			if (this.languageCode != getCommands.languageCode) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.scope == null ? 0 : this.scope.hashCode();
			result = result * 31 + (this.languageCode == null ? 0 : this.languageCode.hashCode());
			return result;
		}
	}

	/**
	 * Returns all website where the current user used Telegram to log in.
	 * <p> Returns {@link ConnectedWebsites ConnectedWebsites} </p>
	**/
	public static final class GetConnectedWebsites extends Function<ConnectedWebsites> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -170536110;

		/**
		 * Returns all website where the current user used Telegram to log in.
		 *
		 * <p> Returns {@link ConnectedWebsites ConnectedWebsites} </p>
		**/
		public GetConnectedWebsites() {}

		/**
		 * Returns all website where the current user used Telegram to log in.
		 *
		 * <p> Returns {@link ConnectedWebsites ConnectedWebsites} </p>
		 *
		 *
		 * <p> Returns {@link ConnectedWebsites ConnectedWebsites} </p>
		**/

		/**
		 * Returns all website where the current user used Telegram to log in.
		 *
		 * <p> Returns {@link ConnectedWebsites ConnectedWebsites} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetConnectedWebsites(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetConnectedWebsites.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetConnectedWebsites.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return GetConnectedWebsites.CONSTRUCTOR;
		}
	}

	/**
	 * Returns all user contacts.
	 * <p> Returns {@link Users Users} </p>
	**/
	public static final class GetContacts extends Function<Users> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1417722768;

		/**
		 * Returns all user contacts.
		 *
		 * <p> Returns {@link Users Users} </p>
		**/
		public GetContacts() {}

		/**
		 * Returns all user contacts.
		 *
		 * <p> Returns {@link Users Users} </p>
		 *
		 *
		 * <p> Returns {@link Users Users} </p>
		**/

		/**
		 * Returns all user contacts.
		 *
		 * <p> Returns {@link Users Users} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetContacts(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetContacts.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetContacts.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return GetContacts.CONSTRUCTOR;
		}
	}

	/**
	 * Returns information about existing countries. Can be called before
	 * authorization.
	 * <p> Returns {@link Countries Countries} </p>
	**/
	public static final class GetCountries extends Function<Countries> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -51902050;

		/**
		 * Returns information about existing countries. Can be called before authorization.
		 *
		 * <p> Returns {@link Countries Countries} </p>
		**/
		public GetCountries() {}

		/**
		 * Returns information about existing countries. Can be called before authorization.
		 *
		 * <p> Returns {@link Countries Countries} </p>
		 *
		 *
		 * <p> Returns {@link Countries Countries} </p>
		**/

		/**
		 * Returns information about existing countries. Can be called before authorization.
		 *
		 * <p> Returns {@link Countries Countries} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetCountries(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetCountries.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetCountries.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return GetCountries.CONSTRUCTOR;
		}
	}

	/**
	 * Uses the current IP address to find the current country. Returns
	 * two-letter ISO 3166-1 alpha-2 country code. Can be called before
	 * authorization.
	 * <p> Returns {@link Text Text} </p>
	**/
	public static final class GetCountryCode extends Function<Text> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1540593906;

		/**
		 * Uses the current IP address to find the current country. Returns two-letter ISO 3166-1 alpha-2 country code. Can be called before authorization.
		 *
		 * <p> Returns {@link Text Text} </p>
		**/
		public GetCountryCode() {}

		/**
		 * Uses the current IP address to find the current country. Returns two-letter ISO 3166-1 alpha-2 country code. Can be called before authorization.
		 *
		 * <p> Returns {@link Text Text} </p>
		 *
		 *
		 * <p> Returns {@link Text Text} </p>
		**/

		/**
		 * Uses the current IP address to find the current country. Returns two-letter ISO 3166-1 alpha-2 country code. Can be called before authorization.
		 *
		 * <p> Returns {@link Text Text} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetCountryCode(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetCountryCode.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetCountryCode.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return GetCountryCode.CONSTRUCTOR;
		}
	}

	/**
	 * Returns a list of public chats of the specified type, owned by the
	 * user.
	 * <p> Returns {@link Chats Chats} </p>
	**/
	public static final class GetCreatedPublicChats extends Function<Chats> {


		/**
		 * Type of the public chats to return.
		**/
		public PublicChatType type;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 710354415;

		/**
		 * Returns a list of public chats of the specified type, owned by the user.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		**/
		public GetCreatedPublicChats() {}

		/**
		 * Returns a list of public chats of the specified type, owned by the user.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		 *
		 * @param type Type of the public chats to return.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		**/
		public GetCreatedPublicChats(PublicChatType type) {
			this.type = type;
		}

		/**
		 * Returns a list of public chats of the specified type, owned by the user.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetCreatedPublicChats(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case PublicChatTypeHasUsername.CONSTRUCTOR: this.type = new PublicChatTypeHasUsername(input); break;
					case PublicChatTypeIsLocationBased.CONSTRUCTOR: this.type = new PublicChatTypeIsLocationBased(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetCreatedPublicChats.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetCreatedPublicChats.CONSTRUCTOR);
			if (this.type == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.type.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetCreatedPublicChats getCreatedPublicChats = (GetCreatedPublicChats) o;
			if (!Objects.equals(this.type, getCreatedPublicChats.type)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.type == null ? 0 : this.type.hashCode();
		}
	}

	/**
	 * Returns all updates needed to restore current TDLib state, i.e. all
	 * actual updateAuthorizationState/updateUser/updateNewChat and others.
	 * This is especially useful if TDLib is run in a separate process. Can
	 * be called before initialization.
	 * <p> Returns {@link Updates Updates} </p>
	**/
	public static final class GetCurrentState extends Function<Updates> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1191417719;

		/**
		 * Returns all updates needed to restore current TDLib state, i.e. all actual updateAuthorizationState/updateUser/updateNewChat and others. This is especially useful if TDLib is run in a separate process. Can be called before initialization.
		 *
		 * <p> Returns {@link Updates Updates} </p>
		**/
		public GetCurrentState() {}

		/**
		 * Returns all updates needed to restore current TDLib state, i.e. all actual updateAuthorizationState/updateUser/updateNewChat and others. This is especially useful if TDLib is run in a separate process. Can be called before initialization.
		 *
		 * <p> Returns {@link Updates Updates} </p>
		 *
		 *
		 * <p> Returns {@link Updates Updates} </p>
		**/

		/**
		 * Returns all updates needed to restore current TDLib state, i.e. all actual updateAuthorizationState/updateUser/updateNewChat and others. This is especially useful if TDLib is run in a separate process. Can be called before initialization.
		 *
		 * <p> Returns {@link Updates Updates} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetCurrentState(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetCurrentState.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetCurrentState.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return GetCurrentState.CONSTRUCTOR;
		}
	}

	/**
	 * Returns TGS stickers with generic animations for custom emoji
	 * reactions.
	 * <p> Returns {@link Stickers Stickers} </p>
	**/
	public static final class GetCustomEmojiReactionAnimations extends Function<Stickers> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1232375250;

		/**
		 * Returns TGS stickers with generic animations for custom emoji reactions.
		 *
		 * <p> Returns {@link Stickers Stickers} </p>
		**/
		public GetCustomEmojiReactionAnimations() {}

		/**
		 * Returns TGS stickers with generic animations for custom emoji reactions.
		 *
		 * <p> Returns {@link Stickers Stickers} </p>
		 *
		 *
		 * <p> Returns {@link Stickers Stickers} </p>
		**/

		/**
		 * Returns TGS stickers with generic animations for custom emoji reactions.
		 *
		 * <p> Returns {@link Stickers Stickers} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetCustomEmojiReactionAnimations(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetCustomEmojiReactionAnimations.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetCustomEmojiReactionAnimations.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return GetCustomEmojiReactionAnimations.CONSTRUCTOR;
		}
	}

	/**
	 * Returns list of custom emoji stickers by their identifiers. Stickers
	 * are returned in arbitrary order. Only found stickers are returned.
	 * <p> Returns {@link Stickers Stickers} </p>
	**/
	public static final class GetCustomEmojiStickers extends Function<Stickers> {


		/**
		 * Identifiers of custom emoji stickers. At most 200 custom emoji stickers can be received simultaneously.
		**/
		public long[] customEmojiIds;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2127427955;

		/**
		 * Returns list of custom emoji stickers by their identifiers. Stickers are returned in arbitrary order. Only found stickers are returned.
		 *
		 * <p> Returns {@link Stickers Stickers} </p>
		**/
		public GetCustomEmojiStickers() {}

		/**
		 * Returns list of custom emoji stickers by their identifiers. Stickers are returned in arbitrary order. Only found stickers are returned.
		 *
		 * <p> Returns {@link Stickers Stickers} </p>
		 *
		 * @param customEmojiIds Identifiers of custom emoji stickers. At most 200 custom emoji stickers can be received simultaneously.
		 *
		 * <p> Returns {@link Stickers Stickers} </p>
		**/
		public GetCustomEmojiStickers(long[] customEmojiIds) {
			this.customEmojiIds = customEmojiIds;
		}

		/**
		 * Returns list of custom emoji stickers by their identifiers. Stickers are returned in arbitrary order. Only found stickers are returned.
		 *
		 * <p> Returns {@link Stickers Stickers} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetCustomEmojiStickers(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.customEmojiIds = new long[input.readInt()];
				for (int i = 0; i < this.customEmojiIds.length; i++) {
					this.customEmojiIds[i] = input.readLong();
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetCustomEmojiStickers.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetCustomEmojiStickers.CONSTRUCTOR);
			if (this.customEmojiIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.customEmojiIds.length);
				for (int i = 0; i < this.customEmojiIds.length; i++) {
					output.writeLong(this.customEmojiIds[i]);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetCustomEmojiStickers getCustomEmojiStickers = (GetCustomEmojiStickers) o;
			if (!Arrays.equals(this.customEmojiIds, getCustomEmojiStickers.customEmojiIds)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.customEmojiIds);
		}
	}

	/**
	 * Returns database statistics.
	 * <p> Returns {@link DatabaseStatistics DatabaseStatistics} </p>
	**/
	public static final class GetDatabaseStatistics extends Function<DatabaseStatistics> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1942760263;

		/**
		 * Returns database statistics.
		 *
		 * <p> Returns {@link DatabaseStatistics DatabaseStatistics} </p>
		**/
		public GetDatabaseStatistics() {}

		/**
		 * Returns database statistics.
		 *
		 * <p> Returns {@link DatabaseStatistics DatabaseStatistics} </p>
		 *
		 *
		 * <p> Returns {@link DatabaseStatistics DatabaseStatistics} </p>
		**/

		/**
		 * Returns database statistics.
		 *
		 * <p> Returns {@link DatabaseStatistics DatabaseStatistics} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetDatabaseStatistics(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetDatabaseStatistics.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetDatabaseStatistics.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return GetDatabaseStatistics.CONSTRUCTOR;
		}
	}

	/**
	 * Returns information about a tg:// deep link. Use
	 * &quot;tg://need_update_for_some_feature&quot; or
	 * &quot;tg:someUnsupportedFeature&quot; for testing. Returns a 404
	 * error for unknown links. Can be called before authorization.
	 * <p> Returns {@link DeepLinkInfo DeepLinkInfo} </p>
	**/
	public static final class GetDeepLinkInfo extends Function<DeepLinkInfo> {


		/**
		 * The link.
		**/
		public String link;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 680673150;

		/**
		 * Returns information about a tg:// deep link. Use &quot;tg://need_update_for_some_feature&quot; or &quot;tg:someUnsupportedFeature&quot; for testing. Returns a 404 error for unknown links. Can be called before authorization.
		 *
		 * <p> Returns {@link DeepLinkInfo DeepLinkInfo} </p>
		**/
		public GetDeepLinkInfo() {}

		/**
		 * Returns information about a tg:// deep link. Use &quot;tg://need_update_for_some_feature&quot; or &quot;tg:someUnsupportedFeature&quot; for testing. Returns a 404 error for unknown links. Can be called before authorization.
		 *
		 * <p> Returns {@link DeepLinkInfo DeepLinkInfo} </p>
		 *
		 * @param link The link.
		 *
		 * <p> Returns {@link DeepLinkInfo DeepLinkInfo} </p>
		**/
		public GetDeepLinkInfo(String link) {
			this.link = link;
		}

		/**
		 * Returns information about a tg:// deep link. Use &quot;tg://need_update_for_some_feature&quot; or &quot;tg:someUnsupportedFeature&quot; for testing. Returns a 404 error for unknown links. Can be called before authorization.
		 *
		 * <p> Returns {@link DeepLinkInfo DeepLinkInfo} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetDeepLinkInfo(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] linkTmp = new byte[input.readInt()];
				input.readFully(linkTmp);
				this.link = new String(linkTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetDeepLinkInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetDeepLinkInfo.CONSTRUCTOR);
			if (this.link == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] linkTmp = this.link.getBytes(StandardCharsets.UTF_8);
				output.writeInt(linkTmp.length);
				output.write(linkTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetDeepLinkInfo getDeepLinkInfo = (GetDeepLinkInfo) o;
			if (this.link != getDeepLinkInfo.link) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.link == null ? 0 : this.link.hashCode();
		}
	}

	/**
	 * Returns default list of custom emoji stickers for placing on a chat
	 * photo.
	 * <p> Returns {@link Stickers Stickers} </p>
	**/
	public static final class GetDefaultChatPhotoCustomEmojiStickers extends Function<Stickers> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -376342683;

		/**
		 * Returns default list of custom emoji stickers for placing on a chat photo.
		 *
		 * <p> Returns {@link Stickers Stickers} </p>
		**/
		public GetDefaultChatPhotoCustomEmojiStickers() {}

		/**
		 * Returns default list of custom emoji stickers for placing on a chat photo.
		 *
		 * <p> Returns {@link Stickers Stickers} </p>
		 *
		 *
		 * <p> Returns {@link Stickers Stickers} </p>
		**/

		/**
		 * Returns default list of custom emoji stickers for placing on a chat photo.
		 *
		 * <p> Returns {@link Stickers Stickers} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetDefaultChatPhotoCustomEmojiStickers(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetDefaultChatPhotoCustomEmojiStickers.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetDefaultChatPhotoCustomEmojiStickers.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return GetDefaultChatPhotoCustomEmojiStickers.CONSTRUCTOR;
		}
	}

	/**
	 * Returns default emoji statuses.
	 * <p> Returns {@link EmojiStatuses EmojiStatuses} </p>
	**/
	public static final class GetDefaultEmojiStatuses extends Function<EmojiStatuses> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 618946243;

		/**
		 * Returns default emoji statuses.
		 *
		 * <p> Returns {@link EmojiStatuses EmojiStatuses} </p>
		**/
		public GetDefaultEmojiStatuses() {}

		/**
		 * Returns default emoji statuses.
		 *
		 * <p> Returns {@link EmojiStatuses EmojiStatuses} </p>
		 *
		 *
		 * <p> Returns {@link EmojiStatuses EmojiStatuses} </p>
		**/

		/**
		 * Returns default emoji statuses.
		 *
		 * <p> Returns {@link EmojiStatuses EmojiStatuses} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetDefaultEmojiStatuses(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetDefaultEmojiStatuses.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetDefaultEmojiStatuses.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return GetDefaultEmojiStatuses.CONSTRUCTOR;
		}
	}

	/**
	 * Returns default message auto-delete time setting for new chats.
	 * <p> Returns {@link MessageAutoDeleteTime MessageAutoDeleteTime} </p>
	**/
	public static final class GetDefaultMessageAutoDeleteTime extends Function<MessageAutoDeleteTime> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -450857574;

		/**
		 * Returns default message auto-delete time setting for new chats.
		 *
		 * <p> Returns {@link MessageAutoDeleteTime MessageAutoDeleteTime} </p>
		**/
		public GetDefaultMessageAutoDeleteTime() {}

		/**
		 * Returns default message auto-delete time setting for new chats.
		 *
		 * <p> Returns {@link MessageAutoDeleteTime MessageAutoDeleteTime} </p>
		 *
		 *
		 * <p> Returns {@link MessageAutoDeleteTime MessageAutoDeleteTime} </p>
		**/

		/**
		 * Returns default message auto-delete time setting for new chats.
		 *
		 * <p> Returns {@link MessageAutoDeleteTime MessageAutoDeleteTime} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetDefaultMessageAutoDeleteTime(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetDefaultMessageAutoDeleteTime.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetDefaultMessageAutoDeleteTime.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return GetDefaultMessageAutoDeleteTime.CONSTRUCTOR;
		}
	}

	/**
	 * Returns default list of custom emoji stickers for placing on a
	 * profile photo.
	 * <p> Returns {@link Stickers Stickers} </p>
	**/
	public static final class GetDefaultProfilePhotoCustomEmojiStickers extends Function<Stickers> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1280041655;

		/**
		 * Returns default list of custom emoji stickers for placing on a profile photo.
		 *
		 * <p> Returns {@link Stickers Stickers} </p>
		**/
		public GetDefaultProfilePhotoCustomEmojiStickers() {}

		/**
		 * Returns default list of custom emoji stickers for placing on a profile photo.
		 *
		 * <p> Returns {@link Stickers Stickers} </p>
		 *
		 *
		 * <p> Returns {@link Stickers Stickers} </p>
		**/

		/**
		 * Returns default list of custom emoji stickers for placing on a profile photo.
		 *
		 * <p> Returns {@link Stickers Stickers} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetDefaultProfilePhotoCustomEmojiStickers(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetDefaultProfilePhotoCustomEmojiStickers.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetDefaultProfilePhotoCustomEmojiStickers.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return GetDefaultProfilePhotoCustomEmojiStickers.CONSTRUCTOR;
		}
	}

	/**
	 * Returns available emojis categories.
	 * <p> Returns {@link EmojiCategories EmojiCategories} </p>
	**/
	public static final class GetEmojiCategories extends Function<EmojiCategories> {


		/**
		 * Type of emoji categories to return; pass null to get default emoji categories.
		**/
		public EmojiCategoryType type;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2139537774;

		/**
		 * Returns available emojis categories.
		 *
		 * <p> Returns {@link EmojiCategories EmojiCategories} </p>
		**/
		public GetEmojiCategories() {}

		/**
		 * Returns available emojis categories.
		 *
		 * <p> Returns {@link EmojiCategories EmojiCategories} </p>
		 *
		 * @param type Type of emoji categories to return; pass null to get default emoji categories.
		 *
		 * <p> Returns {@link EmojiCategories EmojiCategories} </p>
		**/
		public GetEmojiCategories(EmojiCategoryType type) {
			this.type = type;
		}

		/**
		 * Returns available emojis categories.
		 *
		 * <p> Returns {@link EmojiCategories EmojiCategories} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetEmojiCategories(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case EmojiCategoryTypeDefault.CONSTRUCTOR: this.type = new EmojiCategoryTypeDefault(input); break;
					case EmojiCategoryTypeEmojiStatus.CONSTRUCTOR: this.type = new EmojiCategoryTypeEmojiStatus(input); break;
					case EmojiCategoryTypeChatPhoto.CONSTRUCTOR: this.type = new EmojiCategoryTypeChatPhoto(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetEmojiCategories.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetEmojiCategories.CONSTRUCTOR);
			if (this.type == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.type.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetEmojiCategories getEmojiCategories = (GetEmojiCategories) o;
			if (!Objects.equals(this.type, getEmojiCategories.type)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.type == null ? 0 : this.type.hashCode();
		}
	}

	/**
	 * Returns information about a emoji reaction. Returns a 404 error if
	 * the reaction is not found.
	 * <p> Returns {@link EmojiReaction EmojiReaction} </p>
	**/
	public static final class GetEmojiReaction extends Function<EmojiReaction> {


		/**
		 * Text representation of the reaction.
		**/
		public String emoji;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -449572388;

		/**
		 * Returns information about a emoji reaction. Returns a 404 error if the reaction is not found.
		 *
		 * <p> Returns {@link EmojiReaction EmojiReaction} </p>
		**/
		public GetEmojiReaction() {}

		/**
		 * Returns information about a emoji reaction. Returns a 404 error if the reaction is not found.
		 *
		 * <p> Returns {@link EmojiReaction EmojiReaction} </p>
		 *
		 * @param emoji Text representation of the reaction.
		 *
		 * <p> Returns {@link EmojiReaction EmojiReaction} </p>
		**/
		public GetEmojiReaction(String emoji) {
			this.emoji = emoji;
		}

		/**
		 * Returns information about a emoji reaction. Returns a 404 error if the reaction is not found.
		 *
		 * <p> Returns {@link EmojiReaction EmojiReaction} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetEmojiReaction(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] emojiTmp = new byte[input.readInt()];
				input.readFully(emojiTmp);
				this.emoji = new String(emojiTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetEmojiReaction.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetEmojiReaction.CONSTRUCTOR);
			if (this.emoji == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] emojiTmp = this.emoji.getBytes(StandardCharsets.UTF_8);
				output.writeInt(emojiTmp.length);
				output.write(emojiTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetEmojiReaction getEmojiReaction = (GetEmojiReaction) o;
			if (this.emoji != getEmojiReaction.emoji) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.emoji == null ? 0 : this.emoji.hashCode();
		}
	}

	/**
	 * Returns an HTTP URL which can be used to automatically log in to the
	 * translation platform and suggest new emoji replacements. The URL will
	 * be valid for 30 seconds after generation.
	 * <p> Returns {@link HttpUrl HttpUrl} </p>
	**/
	public static final class GetEmojiSuggestionsUrl extends Function<HttpUrl> {


		/**
		 * Language code for which the emoji replacements will be suggested.
		**/
		public String languageCode;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1404101841;

		/**
		 * Returns an HTTP URL which can be used to automatically log in to the translation platform and suggest new emoji replacements. The URL will be valid for 30 seconds after generation.
		 *
		 * <p> Returns {@link HttpUrl HttpUrl} </p>
		**/
		public GetEmojiSuggestionsUrl() {}

		/**
		 * Returns an HTTP URL which can be used to automatically log in to the translation platform and suggest new emoji replacements. The URL will be valid for 30 seconds after generation.
		 *
		 * <p> Returns {@link HttpUrl HttpUrl} </p>
		 *
		 * @param languageCode Language code for which the emoji replacements will be suggested.
		 *
		 * <p> Returns {@link HttpUrl HttpUrl} </p>
		**/
		public GetEmojiSuggestionsUrl(String languageCode) {
			this.languageCode = languageCode;
		}

		/**
		 * Returns an HTTP URL which can be used to automatically log in to the translation platform and suggest new emoji replacements. The URL will be valid for 30 seconds after generation.
		 *
		 * <p> Returns {@link HttpUrl HttpUrl} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetEmojiSuggestionsUrl(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] languageCodeTmp = new byte[input.readInt()];
				input.readFully(languageCodeTmp);
				this.languageCode = new String(languageCodeTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetEmojiSuggestionsUrl.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetEmojiSuggestionsUrl.CONSTRUCTOR);
			if (this.languageCode == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] languageCodeTmp = this.languageCode.getBytes(StandardCharsets.UTF_8);
				output.writeInt(languageCodeTmp.length);
				output.write(languageCodeTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetEmojiSuggestionsUrl getEmojiSuggestionsUrl = (GetEmojiSuggestionsUrl) o;
			if (this.languageCode != getEmojiSuggestionsUrl.languageCode) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.languageCode == null ? 0 : this.languageCode.hashCode();
		}
	}

	/**
	 * Returns an HTTP URL which can be used to automatically authorize the
	 * current user on a website after clicking an HTTP link. Use the method
	 * getExternalLinkInfo to find whether a prior user confirmation is
	 * needed.
	 * <p> Returns {@link HttpUrl HttpUrl} </p>
	**/
	public static final class GetExternalLink extends Function<HttpUrl> {


		/**
		 * The HTTP link.
		**/
		public String link;

		/**
		 * Pass true if the current user allowed the bot, returned in getExternalLinkInfo, to send them messages.
		**/
		public boolean allowWriteAccess;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1586688235;

		/**
		 * Returns an HTTP URL which can be used to automatically authorize the current user on a website after clicking an HTTP link. Use the method getExternalLinkInfo to find whether a prior user confirmation is needed.
		 *
		 * <p> Returns {@link HttpUrl HttpUrl} </p>
		**/
		public GetExternalLink() {}

		/**
		 * Returns an HTTP URL which can be used to automatically authorize the current user on a website after clicking an HTTP link. Use the method getExternalLinkInfo to find whether a prior user confirmation is needed.
		 *
		 * <p> Returns {@link HttpUrl HttpUrl} </p>
		 *
		 * @param link The HTTP link.
		 * @param allowWriteAccess Pass true if the current user allowed the bot, returned in getExternalLinkInfo, to send them messages.
		 *
		 * <p> Returns {@link HttpUrl HttpUrl} </p>
		**/
		public GetExternalLink(String link, boolean allowWriteAccess) {
			this.link = link;
			this.allowWriteAccess = allowWriteAccess;
		}

		/**
		 * Returns an HTTP URL which can be used to automatically authorize the current user on a website after clicking an HTTP link. Use the method getExternalLinkInfo to find whether a prior user confirmation is needed.
		 *
		 * <p> Returns {@link HttpUrl HttpUrl} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetExternalLink(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] linkTmp = new byte[input.readInt()];
				input.readFully(linkTmp);
				this.link = new String(linkTmp, StandardCharsets.UTF_8);
			}
			this.allowWriteAccess = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetExternalLink.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetExternalLink.CONSTRUCTOR);
			if (this.link == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] linkTmp = this.link.getBytes(StandardCharsets.UTF_8);
				output.writeInt(linkTmp.length);
				output.write(linkTmp);
			}
			output.writeBoolean(this.allowWriteAccess);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetExternalLink getExternalLink = (GetExternalLink) o;
			if (this.link != getExternalLink.link) {
				return false;
			}
			if (this.allowWriteAccess != getExternalLink.allowWriteAccess) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.allowWriteAccess);
			result = result * 31 + (this.link == null ? 0 : this.link.hashCode());
			return result;
		}
	}

	/**
	 * Returns information about an action to be done when the current user
	 * clicks an external link. Don&#039;t use this method for links from
	 * secret chats if web page preview is disabled in secret chats.
	 * <p> Returns {@link LoginUrlInfo LoginUrlInfo} </p>
	**/
	public static final class GetExternalLinkInfo extends Function<LoginUrlInfo> {


		/**
		 * The link.
		**/
		public String link;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1175288383;

		/**
		 * Returns information about an action to be done when the current user clicks an external link. Don&#039;t use this method for links from secret chats if web page preview is disabled in secret chats.
		 *
		 * <p> Returns {@link LoginUrlInfo LoginUrlInfo} </p>
		**/
		public GetExternalLinkInfo() {}

		/**
		 * Returns information about an action to be done when the current user clicks an external link. Don&#039;t use this method for links from secret chats if web page preview is disabled in secret chats.
		 *
		 * <p> Returns {@link LoginUrlInfo LoginUrlInfo} </p>
		 *
		 * @param link The link.
		 *
		 * <p> Returns {@link LoginUrlInfo LoginUrlInfo} </p>
		**/
		public GetExternalLinkInfo(String link) {
			this.link = link;
		}

		/**
		 * Returns information about an action to be done when the current user clicks an external link. Don&#039;t use this method for links from secret chats if web page preview is disabled in secret chats.
		 *
		 * <p> Returns {@link LoginUrlInfo LoginUrlInfo} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetExternalLinkInfo(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] linkTmp = new byte[input.readInt()];
				input.readFully(linkTmp);
				this.link = new String(linkTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetExternalLinkInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetExternalLinkInfo.CONSTRUCTOR);
			if (this.link == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] linkTmp = this.link.getBytes(StandardCharsets.UTF_8);
				output.writeInt(linkTmp.length);
				output.write(linkTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetExternalLinkInfo getExternalLinkInfo = (GetExternalLinkInfo) o;
			if (this.link != getExternalLinkInfo.link) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.link == null ? 0 : this.link.hashCode();
		}
	}

	/**
	 * Returns favorite stickers.
	 * <p> Returns {@link Stickers Stickers} </p>
	**/
	public static final class GetFavoriteStickers extends Function<Stickers> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -338964672;

		/**
		 * Returns favorite stickers.
		 *
		 * <p> Returns {@link Stickers Stickers} </p>
		**/
		public GetFavoriteStickers() {}

		/**
		 * Returns favorite stickers.
		 *
		 * <p> Returns {@link Stickers Stickers} </p>
		 *
		 *
		 * <p> Returns {@link Stickers Stickers} </p>
		**/

		/**
		 * Returns favorite stickers.
		 *
		 * <p> Returns {@link Stickers Stickers} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetFavoriteStickers(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetFavoriteStickers.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetFavoriteStickers.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return GetFavoriteStickers.CONSTRUCTOR;
		}
	}

	/**
	 * Returns information about a file; this is an offline request.
	 * <p> Returns {@link File File} </p>
	**/
	public static final class GetFile extends Function<File> {


		/**
		 * Identifier of the file to get.
		**/
		public int fileId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1553923406;

		/**
		 * Returns information about a file; this is an offline request.
		 *
		 * <p> Returns {@link File File} </p>
		**/
		public GetFile() {}

		/**
		 * Returns information about a file; this is an offline request.
		 *
		 * <p> Returns {@link File File} </p>
		 *
		 * @param fileId Identifier of the file to get.
		 *
		 * <p> Returns {@link File File} </p>
		**/
		public GetFile(int fileId) {
			this.fileId = fileId;
		}

		/**
		 * Returns information about a file; this is an offline request.
		 *
		 * <p> Returns {@link File File} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetFile(DataInput input) throws IOException {
			this.fileId = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetFile.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetFile.CONSTRUCTOR);
			output.writeInt(this.fileId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetFile getFile = (GetFile) o;
			if (this.fileId != getFile.fileId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.fileId);
		}
	}

	/**
	 * Returns file downloaded prefix size from a given offset, in bytes.
	 * <p> Returns {@link FileDownloadedPrefixSize FileDownloadedPrefixSize}
	 * </p>
	**/
	public static final class GetFileDownloadedPrefixSize extends Function<FileDownloadedPrefixSize> {


		/**
		 * Identifier of the file.
		**/
		public int fileId;

		/**
		 * Offset from which downloaded prefix size needs to be calculated.
		**/
		public long offset;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 855948589;

		/**
		 * Returns file downloaded prefix size from a given offset, in bytes.
		 *
		 * <p> Returns {@link FileDownloadedPrefixSize FileDownloadedPrefixSize} </p>
		**/
		public GetFileDownloadedPrefixSize() {}

		/**
		 * Returns file downloaded prefix size from a given offset, in bytes.
		 *
		 * <p> Returns {@link FileDownloadedPrefixSize FileDownloadedPrefixSize} </p>
		 *
		 * @param fileId Identifier of the file.
		 * @param offset Offset from which downloaded prefix size needs to be calculated.
		 *
		 * <p> Returns {@link FileDownloadedPrefixSize FileDownloadedPrefixSize} </p>
		**/
		public GetFileDownloadedPrefixSize(int fileId, long offset) {
			this.fileId = fileId;
			this.offset = offset;
		}

		/**
		 * Returns file downloaded prefix size from a given offset, in bytes.
		 *
		 * <p> Returns {@link FileDownloadedPrefixSize FileDownloadedPrefixSize} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetFileDownloadedPrefixSize(DataInput input) throws IOException {
			this.fileId = input.readInt();
			this.offset = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetFileDownloadedPrefixSize.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetFileDownloadedPrefixSize.CONSTRUCTOR);
			output.writeInt(this.fileId);
			output.writeLong(this.offset);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetFileDownloadedPrefixSize getFileDownloadedPrefixSize = (GetFileDownloadedPrefixSize) o;
			if (this.fileId != getFileDownloadedPrefixSize.fileId) {
				return false;
			}
			if (this.offset != getFileDownloadedPrefixSize.offset) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.fileId);
			return result;
		}
	}

	/**
	 * Returns the extension of a file, guessed by its MIME type. Returns an
	 * empty string on failure. Can be called synchronously.
	 * <p> Returns {@link Text Text} </p>
	**/
	public static final class GetFileExtension extends Function<Text> {


		/**
		 * The MIME type of the file.
		**/
		public String mimeType;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -106055372;

		/**
		 * Returns the extension of a file, guessed by its MIME type. Returns an empty string on failure. Can be called synchronously.
		 *
		 * <p> Returns {@link Text Text} </p>
		**/
		public GetFileExtension() {}

		/**
		 * Returns the extension of a file, guessed by its MIME type. Returns an empty string on failure. Can be called synchronously.
		 *
		 * <p> Returns {@link Text Text} </p>
		 *
		 * @param mimeType The MIME type of the file.
		 *
		 * <p> Returns {@link Text Text} </p>
		**/
		public GetFileExtension(String mimeType) {
			this.mimeType = mimeType;
		}

		/**
		 * Returns the extension of a file, guessed by its MIME type. Returns an empty string on failure. Can be called synchronously.
		 *
		 * <p> Returns {@link Text Text} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetFileExtension(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] mimeTypeTmp = new byte[input.readInt()];
				input.readFully(mimeTypeTmp);
				this.mimeType = new String(mimeTypeTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetFileExtension.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetFileExtension.CONSTRUCTOR);
			if (this.mimeType == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] mimeTypeTmp = this.mimeType.getBytes(StandardCharsets.UTF_8);
				output.writeInt(mimeTypeTmp.length);
				output.write(mimeTypeTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetFileExtension getFileExtension = (GetFileExtension) o;
			if (this.mimeType != getFileExtension.mimeType) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.mimeType == null ? 0 : this.mimeType.hashCode();
		}
	}

	/**
	 * Returns the MIME type of a file, guessed by its extension. Returns an
	 * empty string on failure. Can be called synchronously.
	 * <p> Returns {@link Text Text} </p>
	**/
	public static final class GetFileMimeType extends Function<Text> {


		/**
		 * The name of the file or path to the file.
		**/
		public String fileName;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2073879671;

		/**
		 * Returns the MIME type of a file, guessed by its extension. Returns an empty string on failure. Can be called synchronously.
		 *
		 * <p> Returns {@link Text Text} </p>
		**/
		public GetFileMimeType() {}

		/**
		 * Returns the MIME type of a file, guessed by its extension. Returns an empty string on failure. Can be called synchronously.
		 *
		 * <p> Returns {@link Text Text} </p>
		 *
		 * @param fileName The name of the file or path to the file.
		 *
		 * <p> Returns {@link Text Text} </p>
		**/
		public GetFileMimeType(String fileName) {
			this.fileName = fileName;
		}

		/**
		 * Returns the MIME type of a file, guessed by its extension. Returns an empty string on failure. Can be called synchronously.
		 *
		 * <p> Returns {@link Text Text} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetFileMimeType(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] fileNameTmp = new byte[input.readInt()];
				input.readFully(fileNameTmp);
				this.fileName = new String(fileNameTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetFileMimeType.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetFileMimeType.CONSTRUCTOR);
			if (this.fileName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] fileNameTmp = this.fileName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(fileNameTmp.length);
				output.write(fileNameTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetFileMimeType getFileMimeType = (GetFileMimeType) o;
			if (this.fileName != getFileMimeType.fileName) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.fileName == null ? 0 : this.fileName.hashCode();
		}
	}

	/**
	 * Returns information about a forum topic.
	 * <p> Returns {@link ForumTopic ForumTopic} </p>
	**/
	public static final class GetForumTopic extends Function<ForumTopic> {


		/**
		 * Identifier of the chat.
		**/
		public long chatId;

		/**
		 * Message thread identifier of the forum topic.
		**/
		public long messageThreadId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -442761663;

		/**
		 * Returns information about a forum topic.
		 *
		 * <p> Returns {@link ForumTopic ForumTopic} </p>
		**/
		public GetForumTopic() {}

		/**
		 * Returns information about a forum topic.
		 *
		 * <p> Returns {@link ForumTopic ForumTopic} </p>
		 *
		 * @param chatId Identifier of the chat.
		 * @param messageThreadId Message thread identifier of the forum topic.
		 *
		 * <p> Returns {@link ForumTopic ForumTopic} </p>
		**/
		public GetForumTopic(long chatId, long messageThreadId) {
			this.chatId = chatId;
			this.messageThreadId = messageThreadId;
		}

		/**
		 * Returns information about a forum topic.
		 *
		 * <p> Returns {@link ForumTopic ForumTopic} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetForumTopic(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageThreadId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetForumTopic.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetForumTopic.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageThreadId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetForumTopic getForumTopic = (GetForumTopic) o;
			if (this.chatId != getForumTopic.chatId) {
				return false;
			}
			if (this.messageThreadId != getForumTopic.messageThreadId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Returns list of custom emojis, which can be used as forum topic icon
	 * by all users.
	 * <p> Returns {@link Stickers Stickers} </p>
	**/
	public static final class GetForumTopicDefaultIcons extends Function<Stickers> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1479898332;

		/**
		 * Returns list of custom emojis, which can be used as forum topic icon by all users.
		 *
		 * <p> Returns {@link Stickers Stickers} </p>
		**/
		public GetForumTopicDefaultIcons() {}

		/**
		 * Returns list of custom emojis, which can be used as forum topic icon by all users.
		 *
		 * <p> Returns {@link Stickers Stickers} </p>
		 *
		 *
		 * <p> Returns {@link Stickers Stickers} </p>
		**/

		/**
		 * Returns list of custom emojis, which can be used as forum topic icon by all users.
		 *
		 * <p> Returns {@link Stickers Stickers} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetForumTopicDefaultIcons(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetForumTopicDefaultIcons.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetForumTopicDefaultIcons.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return GetForumTopicDefaultIcons.CONSTRUCTOR;
		}
	}

	/**
	 * Returns an HTTPS link to a topic in a forum chat. This is an offline
	 * request.
	 * <p> Returns {@link MessageLink MessageLink} </p>
	**/
	public static final class GetForumTopicLink extends Function<MessageLink> {


		/**
		 * Identifier of the chat.
		**/
		public long chatId;

		/**
		 * Message thread identifier of the forum topic.
		**/
		public long messageThreadId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -914650933;

		/**
		 * Returns an HTTPS link to a topic in a forum chat. This is an offline request.
		 *
		 * <p> Returns {@link MessageLink MessageLink} </p>
		**/
		public GetForumTopicLink() {}

		/**
		 * Returns an HTTPS link to a topic in a forum chat. This is an offline request.
		 *
		 * <p> Returns {@link MessageLink MessageLink} </p>
		 *
		 * @param chatId Identifier of the chat.
		 * @param messageThreadId Message thread identifier of the forum topic.
		 *
		 * <p> Returns {@link MessageLink MessageLink} </p>
		**/
		public GetForumTopicLink(long chatId, long messageThreadId) {
			this.chatId = chatId;
			this.messageThreadId = messageThreadId;
		}

		/**
		 * Returns an HTTPS link to a topic in a forum chat. This is an offline request.
		 *
		 * <p> Returns {@link MessageLink MessageLink} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetForumTopicLink(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageThreadId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetForumTopicLink.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetForumTopicLink.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageThreadId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetForumTopicLink getForumTopicLink = (GetForumTopicLink) o;
			if (this.chatId != getForumTopicLink.chatId) {
				return false;
			}
			if (this.messageThreadId != getForumTopicLink.messageThreadId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Returns found forum topics in a forum chat. This is a temporary
	 * method for getting information about topic list from the server.
	 * <p> Returns {@link ForumTopics ForumTopics} </p>
	**/
	public static final class GetForumTopics extends Function<ForumTopics> {


		/**
		 * Identifier of the forum chat.
		**/
		public long chatId;

		/**
		 * Query to search for in the forum topic&#039;s name.
		**/
		public String query;

		/**
		 * The date starting from which the results need to be fetched. Use 0 or any date in the future to get results from the last topic.
		**/
		public int offsetDate;

		/**
		 * The message identifier of the last message in the last found topic, or 0 for the first request.
		**/
		public long offsetMessageId;

		/**
		 * The message thread identifier of the last found topic, or 0 for the first request.
		**/
		public long offsetMessageThreadId;

		/**
		 * The maximum number of forum topics to be returned; up to 100. For optimal performance, the number of returned forum topics is chosen by TDLib and can be smaller than the specified limit.
		**/
		public int limit;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -72647334;

		/**
		 * Returns found forum topics in a forum chat. This is a temporary method for getting information about topic list from the server.
		 *
		 * <p> Returns {@link ForumTopics ForumTopics} </p>
		**/
		public GetForumTopics() {}

		/**
		 * Returns found forum topics in a forum chat. This is a temporary method for getting information about topic list from the server.
		 *
		 * <p> Returns {@link ForumTopics ForumTopics} </p>
		 *
		 * @param chatId Identifier of the forum chat.
		 * @param query Query to search for in the forum topic&#039;s name.
		 * @param offsetDate The date starting from which the results need to be fetched. Use 0 or any date in the future to get results from the last topic.
		 * @param offsetMessageId The message identifier of the last message in the last found topic, or 0 for the first request.
		 * @param offsetMessageThreadId The message thread identifier of the last found topic, or 0 for the first request.
		 * @param limit The maximum number of forum topics to be returned; up to 100. For optimal performance, the number of returned forum topics is chosen by TDLib and can be smaller than the specified limit.
		 *
		 * <p> Returns {@link ForumTopics ForumTopics} </p>
		**/
		public GetForumTopics(long chatId,
				String query,
				int offsetDate,
				long offsetMessageId,
				long offsetMessageThreadId,
				int limit) {
			this.chatId = chatId;
			this.query = query;
			this.offsetDate = offsetDate;
			this.offsetMessageId = offsetMessageId;
			this.offsetMessageThreadId = offsetMessageThreadId;
			this.limit = limit;
		}

		/**
		 * Returns found forum topics in a forum chat. This is a temporary method for getting information about topic list from the server.
		 *
		 * <p> Returns {@link ForumTopics ForumTopics} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetForumTopics(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				byte[] queryTmp = new byte[input.readInt()];
				input.readFully(queryTmp);
				this.query = new String(queryTmp, StandardCharsets.UTF_8);
			}
			this.offsetDate = input.readInt();
			this.offsetMessageId = input.readLong();
			this.offsetMessageThreadId = input.readLong();
			this.limit = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetForumTopics.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetForumTopics.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.query == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] queryTmp = this.query.getBytes(StandardCharsets.UTF_8);
				output.writeInt(queryTmp.length);
				output.write(queryTmp);
			}
			output.writeInt(this.offsetDate);
			output.writeLong(this.offsetMessageId);
			output.writeLong(this.offsetMessageThreadId);
			output.writeInt(this.limit);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetForumTopics getForumTopics = (GetForumTopics) o;
			if (this.chatId != getForumTopics.chatId) {
				return false;
			}
			if (this.query != getForumTopics.query) {
				return false;
			}
			if (this.offsetDate != getForumTopics.offsetDate) {
				return false;
			}
			if (this.offsetMessageId != getForumTopics.offsetMessageId) {
				return false;
			}
			if (this.offsetMessageThreadId != getForumTopics.offsetMessageThreadId) {
				return false;
			}
			if (this.limit != getForumTopics.limit) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.query == null ? 0 : this.query.hashCode());
			return result;
		}
	}

	/**
	 * Returns the high scores for a game and some part of the high score
	 * table in the range of the specified user; for bots only.
	 * <p> Returns {@link GameHighScores GameHighScores} </p>
	**/
	public static final class GetGameHighScores extends Function<GameHighScores> {


		/**
		 * The chat that contains the message with the game.
		**/
		public long chatId;

		/**
		 * Identifier of the message.
		**/
		public long messageId;

		/**
		 * User identifier.
		**/
		public long userId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 15746459;

		/**
		 * Returns the high scores for a game and some part of the high score table in the range of the specified user; for bots only.
		 *
		 * <p> Returns {@link GameHighScores GameHighScores} </p>
		**/
		public GetGameHighScores() {}

		/**
		 * Returns the high scores for a game and some part of the high score table in the range of the specified user; for bots only.
		 *
		 * <p> Returns {@link GameHighScores GameHighScores} </p>
		 *
		 * @param chatId The chat that contains the message with the game.
		 * @param messageId Identifier of the message.
		 * @param userId User identifier.
		 *
		 * <p> Returns {@link GameHighScores GameHighScores} </p>
		**/
		public GetGameHighScores(long chatId, long messageId, long userId) {
			this.chatId = chatId;
			this.messageId = messageId;
			this.userId = userId;
		}

		/**
		 * Returns the high scores for a game and some part of the high score table in the range of the specified user; for bots only.
		 *
		 * <p> Returns {@link GameHighScores GameHighScores} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetGameHighScores(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
			this.userId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetGameHighScores.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetGameHighScores.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
			output.writeLong(this.userId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetGameHighScores getGameHighScores = (GetGameHighScores) o;
			if (this.chatId != getGameHighScores.chatId) {
				return false;
			}
			if (this.messageId != getGameHighScores.messageId) {
				return false;
			}
			if (this.userId != getGameHighScores.userId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Returns information about a group call.
	 * <p> Returns {@link GroupCall GroupCall} </p>
	**/
	public static final class GetGroupCall extends Function<GroupCall> {


		/**
		 * Group call identifier.
		**/
		public int groupCallId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1468491406;

		/**
		 * Returns information about a group call.
		 *
		 * <p> Returns {@link GroupCall GroupCall} </p>
		**/
		public GetGroupCall() {}

		/**
		 * Returns information about a group call.
		 *
		 * <p> Returns {@link GroupCall GroupCall} </p>
		 *
		 * @param groupCallId Group call identifier.
		 *
		 * <p> Returns {@link GroupCall GroupCall} </p>
		**/
		public GetGroupCall(int groupCallId) {
			this.groupCallId = groupCallId;
		}

		/**
		 * Returns information about a group call.
		 *
		 * <p> Returns {@link GroupCall GroupCall} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetGroupCall(DataInput input) throws IOException {
			this.groupCallId = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetGroupCall.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetGroupCall.CONSTRUCTOR);
			output.writeInt(this.groupCallId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetGroupCall getGroupCall = (GetGroupCall) o;
			if (this.groupCallId != getGroupCall.groupCallId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.groupCallId);
		}
	}

	/**
	 * Returns invite link to a video chat in a public chat.
	 * <p> Returns {@link HttpUrl HttpUrl} </p>
	**/
	public static final class GetGroupCallInviteLink extends Function<HttpUrl> {


		/**
		 * Group call identifier.
		**/
		public int groupCallId;

		/**
		 * Pass true if the invite link needs to contain an invite hash, passing which to joinGroupCall would allow the invited user to unmute themselves. Requires groupCall.canBeManaged group call flag.
		**/
		public boolean canSelfUnmute;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 719407396;

		/**
		 * Returns invite link to a video chat in a public chat.
		 *
		 * <p> Returns {@link HttpUrl HttpUrl} </p>
		**/
		public GetGroupCallInviteLink() {}

		/**
		 * Returns invite link to a video chat in a public chat.
		 *
		 * <p> Returns {@link HttpUrl HttpUrl} </p>
		 *
		 * @param groupCallId Group call identifier.
		 * @param canSelfUnmute Pass true if the invite link needs to contain an invite hash, passing which to joinGroupCall would allow the invited user to unmute themselves. Requires groupCall.canBeManaged group call flag.
		 *
		 * <p> Returns {@link HttpUrl HttpUrl} </p>
		**/
		public GetGroupCallInviteLink(int groupCallId, boolean canSelfUnmute) {
			this.groupCallId = groupCallId;
			this.canSelfUnmute = canSelfUnmute;
		}

		/**
		 * Returns invite link to a video chat in a public chat.
		 *
		 * <p> Returns {@link HttpUrl HttpUrl} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetGroupCallInviteLink(DataInput input) throws IOException {
			this.groupCallId = input.readInt();
			this.canSelfUnmute = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetGroupCallInviteLink.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetGroupCallInviteLink.CONSTRUCTOR);
			output.writeInt(this.groupCallId);
			output.writeBoolean(this.canSelfUnmute);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetGroupCallInviteLink getGroupCallInviteLink = (GetGroupCallInviteLink) o;
			if (this.groupCallId != getGroupCallInviteLink.groupCallId) {
				return false;
			}
			if (this.canSelfUnmute != getGroupCallInviteLink.canSelfUnmute) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.groupCallId);
			return result;
		}
	}

	/**
	 * Returns a file with a segment of a group call stream in a modified
	 * OGG format for audio or MPEG-4 format for video.
	 * <p> Returns {@link FilePart FilePart} </p>
	**/
	public static final class GetGroupCallStreamSegment extends Function<FilePart> {


		/**
		 * Group call identifier.
		**/
		public int groupCallId;

		/**
		 * Point in time when the stream segment begins; Unix timestamp in milliseconds.
		**/
		public long timeOffset;

		/**
		 * Segment duration scale; 0-1. Segment&#039;s duration is 1000/(2**scale) milliseconds.
		**/
		public int scale;

		/**
		 * Identifier of an audio/video channel to get as received from tgcalls.
		**/
		public int channelId;

		/**
		 * Video quality as received from tgcalls; pass null to get the worst available quality.
		**/
		public GroupCallVideoQuality videoQuality;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2077959515;

		/**
		 * Returns a file with a segment of a group call stream in a modified OGG format for audio or MPEG-4 format for video.
		 *
		 * <p> Returns {@link FilePart FilePart} </p>
		**/
		public GetGroupCallStreamSegment() {}

		/**
		 * Returns a file with a segment of a group call stream in a modified OGG format for audio or MPEG-4 format for video.
		 *
		 * <p> Returns {@link FilePart FilePart} </p>
		 *
		 * @param groupCallId Group call identifier.
		 * @param timeOffset Point in time when the stream segment begins; Unix timestamp in milliseconds.
		 * @param scale Segment duration scale; 0-1. Segment&#039;s duration is 1000/(2**scale) milliseconds.
		 * @param channelId Identifier of an audio/video channel to get as received from tgcalls.
		 * @param videoQuality Video quality as received from tgcalls; pass null to get the worst available quality.
		 *
		 * <p> Returns {@link FilePart FilePart} </p>
		**/
		public GetGroupCallStreamSegment(int groupCallId,
				long timeOffset,
				int scale,
				int channelId,
				GroupCallVideoQuality videoQuality) {
			this.groupCallId = groupCallId;
			this.timeOffset = timeOffset;
			this.scale = scale;
			this.channelId = channelId;
			this.videoQuality = videoQuality;
		}

		/**
		 * Returns a file with a segment of a group call stream in a modified OGG format for audio or MPEG-4 format for video.
		 *
		 * <p> Returns {@link FilePart FilePart} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetGroupCallStreamSegment(DataInput input) throws IOException {
			this.groupCallId = input.readInt();
			this.timeOffset = input.readLong();
			this.scale = input.readInt();
			this.channelId = input.readInt();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case GroupCallVideoQualityThumbnail.CONSTRUCTOR: this.videoQuality = new GroupCallVideoQualityThumbnail(input); break;
					case GroupCallVideoQualityMedium.CONSTRUCTOR: this.videoQuality = new GroupCallVideoQualityMedium(input); break;
					case GroupCallVideoQualityFull.CONSTRUCTOR: this.videoQuality = new GroupCallVideoQualityFull(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetGroupCallStreamSegment.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetGroupCallStreamSegment.CONSTRUCTOR);
			output.writeInt(this.groupCallId);
			output.writeLong(this.timeOffset);
			output.writeInt(this.scale);
			output.writeInt(this.channelId);
			if (this.videoQuality == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.videoQuality.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetGroupCallStreamSegment getGroupCallStreamSegment = (GetGroupCallStreamSegment) o;
			if (this.groupCallId != getGroupCallStreamSegment.groupCallId) {
				return false;
			}
			if (this.timeOffset != getGroupCallStreamSegment.timeOffset) {
				return false;
			}
			if (this.scale != getGroupCallStreamSegment.scale) {
				return false;
			}
			if (this.channelId != getGroupCallStreamSegment.channelId) {
				return false;
			}
			if (!Objects.equals(this.videoQuality, getGroupCallStreamSegment.videoQuality)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.groupCallId);
			result = result * 31 + (this.videoQuality == null ? 0 : this.videoQuality.hashCode());
			return result;
		}
	}

	/**
	 * Returns information about available group call streams.
	 * <p> Returns {@link GroupCallStreams GroupCallStreams} </p>
	**/
	public static final class GetGroupCallStreams extends Function<GroupCallStreams> {


		/**
		 * Group call identifier.
		**/
		public int groupCallId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1619226268;

		/**
		 * Returns information about available group call streams.
		 *
		 * <p> Returns {@link GroupCallStreams GroupCallStreams} </p>
		**/
		public GetGroupCallStreams() {}

		/**
		 * Returns information about available group call streams.
		 *
		 * <p> Returns {@link GroupCallStreams GroupCallStreams} </p>
		 *
		 * @param groupCallId Group call identifier.
		 *
		 * <p> Returns {@link GroupCallStreams GroupCallStreams} </p>
		**/
		public GetGroupCallStreams(int groupCallId) {
			this.groupCallId = groupCallId;
		}

		/**
		 * Returns information about available group call streams.
		 *
		 * <p> Returns {@link GroupCallStreams GroupCallStreams} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetGroupCallStreams(DataInput input) throws IOException {
			this.groupCallId = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetGroupCallStreams.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetGroupCallStreams.CONSTRUCTOR);
			output.writeInt(this.groupCallId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetGroupCallStreams getGroupCallStreams = (GetGroupCallStreams) o;
			if (this.groupCallId != getGroupCallStreams.groupCallId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.groupCallId);
		}
	}

	/**
	 * Returns a list of common group chats with a given user. Chats are
	 * sorted by their type and creation date.
	 * <p> Returns {@link Chats Chats} </p>
	**/
	public static final class GetGroupsInCommon extends Function<Chats> {


		/**
		 * User identifier.
		**/
		public long userId;

		/**
		 * Chat identifier starting from which to return chats; use 0 for the first request.
		**/
		public long offsetChatId;

		/**
		 * The maximum number of chats to be returned; up to 100.
		**/
		public int limit;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 381539178;

		/**
		 * Returns a list of common group chats with a given user. Chats are sorted by their type and creation date.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		**/
		public GetGroupsInCommon() {}

		/**
		 * Returns a list of common group chats with a given user. Chats are sorted by their type and creation date.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		 *
		 * @param userId User identifier.
		 * @param offsetChatId Chat identifier starting from which to return chats; use 0 for the first request.
		 * @param limit The maximum number of chats to be returned; up to 100.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		**/
		public GetGroupsInCommon(long userId, long offsetChatId, int limit) {
			this.userId = userId;
			this.offsetChatId = offsetChatId;
			this.limit = limit;
		}

		/**
		 * Returns a list of common group chats with a given user. Chats are sorted by their type and creation date.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetGroupsInCommon(DataInput input) throws IOException {
			this.userId = input.readLong();
			this.offsetChatId = input.readLong();
			this.limit = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetGroupsInCommon.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetGroupsInCommon.CONSTRUCTOR);
			output.writeLong(this.userId);
			output.writeLong(this.offsetChatId);
			output.writeInt(this.limit);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetGroupsInCommon getGroupsInCommon = (GetGroupsInCommon) o;
			if (this.userId != getGroupsInCommon.userId) {
				return false;
			}
			if (this.offsetChatId != getGroupsInCommon.offsetChatId) {
				return false;
			}
			if (this.limit != getGroupsInCommon.limit) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.userId);
			return result;
		}
	}

	/**
	 * Returns the total number of imported contacts.
	 * <p> Returns {@link Count Count} </p>
	**/
	public static final class GetImportedContactCount extends Function<Count> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -656336346;

		/**
		 * Returns the total number of imported contacts.
		 *
		 * <p> Returns {@link Count Count} </p>
		**/
		public GetImportedContactCount() {}

		/**
		 * Returns the total number of imported contacts.
		 *
		 * <p> Returns {@link Count Count} </p>
		 *
		 *
		 * <p> Returns {@link Count Count} </p>
		**/

		/**
		 * Returns the total number of imported contacts.
		 *
		 * <p> Returns {@link Count Count} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetImportedContactCount(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetImportedContactCount.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetImportedContactCount.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return GetImportedContactCount.CONSTRUCTOR;
		}
	}

	/**
	 * Returns a list of recently inactive supergroups and channels. Can be
	 * used when user reaches limit on the number of joined supergroups and
	 * channels and receives CHANNELSTOOMUCH error. Also, the limit can be
	 * increased with Telegram Premium.
	 * <p> Returns {@link Chats Chats} </p>
	**/
	public static final class GetInactiveSupergroupChats extends Function<Chats> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -657720907;

		/**
		 * Returns a list of recently inactive supergroups and channels. Can be used when user reaches limit on the number of joined supergroups and channels and receives CHANNELSTOOMUCH error. Also, the limit can be increased with Telegram Premium.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		**/
		public GetInactiveSupergroupChats() {}

		/**
		 * Returns a list of recently inactive supergroups and channels. Can be used when user reaches limit on the number of joined supergroups and channels and receives CHANNELSTOOMUCH error. Also, the limit can be increased with Telegram Premium.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		 *
		 *
		 * <p> Returns {@link Chats Chats} </p>
		**/

		/**
		 * Returns a list of recently inactive supergroups and channels. Can be used when user reaches limit on the number of joined supergroups and channels and receives CHANNELSTOOMUCH error. Also, the limit can be increased with Telegram Premium.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetInactiveSupergroupChats(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetInactiveSupergroupChats.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetInactiveSupergroupChats.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return GetInactiveSupergroupChats.CONSTRUCTOR;
		}
	}

	/**
	 * Returns game high scores and some part of the high score table in the
	 * range of the specified user; for bots only.
	 * <p> Returns {@link GameHighScores GameHighScores} </p>
	**/
	public static final class GetInlineGameHighScores extends Function<GameHighScores> {


		/**
		 * Inline message identifier.
		**/
		public String inlineMessageId;

		/**
		 * User identifier.
		**/
		public long userId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -533107798;

		/**
		 * Returns game high scores and some part of the high score table in the range of the specified user; for bots only.
		 *
		 * <p> Returns {@link GameHighScores GameHighScores} </p>
		**/
		public GetInlineGameHighScores() {}

		/**
		 * Returns game high scores and some part of the high score table in the range of the specified user; for bots only.
		 *
		 * <p> Returns {@link GameHighScores GameHighScores} </p>
		 *
		 * @param inlineMessageId Inline message identifier.
		 * @param userId User identifier.
		 *
		 * <p> Returns {@link GameHighScores GameHighScores} </p>
		**/
		public GetInlineGameHighScores(String inlineMessageId, long userId) {
			this.inlineMessageId = inlineMessageId;
			this.userId = userId;
		}

		/**
		 * Returns game high scores and some part of the high score table in the range of the specified user; for bots only.
		 *
		 * <p> Returns {@link GameHighScores GameHighScores} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetInlineGameHighScores(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] inlineMessageIdTmp = new byte[input.readInt()];
				input.readFully(inlineMessageIdTmp);
				this.inlineMessageId = new String(inlineMessageIdTmp, StandardCharsets.UTF_8);
			}
			this.userId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetInlineGameHighScores.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetInlineGameHighScores.CONSTRUCTOR);
			if (this.inlineMessageId == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] inlineMessageIdTmp = this.inlineMessageId.getBytes(StandardCharsets.UTF_8);
				output.writeInt(inlineMessageIdTmp.length);
				output.write(inlineMessageIdTmp);
			}
			output.writeLong(this.userId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetInlineGameHighScores getInlineGameHighScores = (GetInlineGameHighScores) o;
			if (this.inlineMessageId != getInlineGameHighScores.inlineMessageId) {
				return false;
			}
			if (this.userId != getInlineGameHighScores.userId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.userId);
			result = result * 31 + (this.inlineMessageId == null ? 0 : this.inlineMessageId.hashCode());
			return result;
		}
	}

	/**
	 * Sends an inline query to a bot and returns its results. Returns an
	 * error with code 502 if the bot fails to answer the query before the
	 * query timeout expires.
	 * <p> Returns {@link InlineQueryResults InlineQueryResults} </p>
	**/
	public static final class GetInlineQueryResults extends Function<InlineQueryResults> {


		/**
		 * Identifier of the target bot.
		**/
		public long botUserId;

		/**
		 * Identifier of the chat where the query was sent.
		**/
		public long chatId;

		/**
		 * Location of the user; pass null if unknown or the bot doesn&#039;t need user&#039;s location.
		**/
		public Location userLocation;

		/**
		 * Text of the query.
		**/
		public String query;

		/**
		 * Offset of the first entry to return.
		**/
		public String offset;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2044524652;

		/**
		 * Sends an inline query to a bot and returns its results. Returns an error with code 502 if the bot fails to answer the query before the query timeout expires.
		 *
		 * <p> Returns {@link InlineQueryResults InlineQueryResults} </p>
		**/
		public GetInlineQueryResults() {}

		/**
		 * Sends an inline query to a bot and returns its results. Returns an error with code 502 if the bot fails to answer the query before the query timeout expires.
		 *
		 * <p> Returns {@link InlineQueryResults InlineQueryResults} </p>
		 *
		 * @param botUserId Identifier of the target bot.
		 * @param chatId Identifier of the chat where the query was sent.
		 * @param userLocation Location of the user; pass null if unknown or the bot doesn&#039;t need user&#039;s location.
		 * @param query Text of the query.
		 * @param offset Offset of the first entry to return.
		 *
		 * <p> Returns {@link InlineQueryResults InlineQueryResults} </p>
		**/
		public GetInlineQueryResults(long botUserId,
				long chatId,
				Location userLocation,
				String query,
				String offset) {
			this.botUserId = botUserId;
			this.chatId = chatId;
			this.userLocation = userLocation;
			this.query = query;
			this.offset = offset;
		}

		/**
		 * Sends an inline query to a bot and returns its results. Returns an error with code 502 if the bot fails to answer the query before the query timeout expires.
		 *
		 * <p> Returns {@link InlineQueryResults InlineQueryResults} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetInlineQueryResults(DataInput input) throws IOException {
			this.botUserId = input.readLong();
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				if (Location.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.userLocation = new Location(input);
			}
			if (input.readBoolean()) {
				byte[] queryTmp = new byte[input.readInt()];
				input.readFully(queryTmp);
				this.query = new String(queryTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] offsetTmp = new byte[input.readInt()];
				input.readFully(offsetTmp);
				this.offset = new String(offsetTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetInlineQueryResults.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetInlineQueryResults.CONSTRUCTOR);
			output.writeLong(this.botUserId);
			output.writeLong(this.chatId);
			if (this.userLocation == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.userLocation.serialize(output);
			}
			if (this.query == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] queryTmp = this.query.getBytes(StandardCharsets.UTF_8);
				output.writeInt(queryTmp.length);
				output.write(queryTmp);
			}
			if (this.offset == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] offsetTmp = this.offset.getBytes(StandardCharsets.UTF_8);
				output.writeInt(offsetTmp.length);
				output.write(offsetTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetInlineQueryResults getInlineQueryResults = (GetInlineQueryResults) o;
			if (this.botUserId != getInlineQueryResults.botUserId) {
				return false;
			}
			if (this.chatId != getInlineQueryResults.chatId) {
				return false;
			}
			if (!Objects.equals(this.userLocation, getInlineQueryResults.userLocation)) {
				return false;
			}
			if (this.query != getInlineQueryResults.query) {
				return false;
			}
			if (this.offset != getInlineQueryResults.offset) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.botUserId);
			result = result * 31 + (this.userLocation == null ? 0 : this.userLocation.hashCode());
			result = result * 31 + (this.query == null ? 0 : this.query.hashCode());
			result = result * 31 + (this.offset == null ? 0 : this.offset.hashCode());
			return result;
		}
	}

	/**
	 * Returns a list of installed sticker sets.
	 * <p> Returns {@link StickerSets StickerSets} </p>
	**/
	public static final class GetInstalledStickerSets extends Function<StickerSets> {


		/**
		 * Type of the sticker sets to return.
		**/
		public StickerType stickerType;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1630467830;

		/**
		 * Returns a list of installed sticker sets.
		 *
		 * <p> Returns {@link StickerSets StickerSets} </p>
		**/
		public GetInstalledStickerSets() {}

		/**
		 * Returns a list of installed sticker sets.
		 *
		 * <p> Returns {@link StickerSets StickerSets} </p>
		 *
		 * @param stickerType Type of the sticker sets to return.
		 *
		 * <p> Returns {@link StickerSets StickerSets} </p>
		**/
		public GetInstalledStickerSets(StickerType stickerType) {
			this.stickerType = stickerType;
		}

		/**
		 * Returns a list of installed sticker sets.
		 *
		 * <p> Returns {@link StickerSets StickerSets} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetInstalledStickerSets(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case StickerTypeRegular.CONSTRUCTOR: this.stickerType = new StickerTypeRegular(input); break;
					case StickerTypeMask.CONSTRUCTOR: this.stickerType = new StickerTypeMask(input); break;
					case StickerTypeCustomEmoji.CONSTRUCTOR: this.stickerType = new StickerTypeCustomEmoji(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetInstalledStickerSets.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetInstalledStickerSets.CONSTRUCTOR);
			if (this.stickerType == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.stickerType.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetInstalledStickerSets getInstalledStickerSets = (GetInstalledStickerSets) o;
			if (!Objects.equals(this.stickerType, getInstalledStickerSets.stickerType)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.stickerType == null ? 0 : this.stickerType.hashCode();
		}
	}

	/**
	 * Returns an HTTPS or a tg: link with the given type. Can be called
	 * before authorization.
	 * <p> Returns {@link HttpUrl HttpUrl} </p>
	**/
	public static final class GetInternalLink extends Function<HttpUrl> {


		/**
		 * Expected type of the link.
		**/
		public InternalLinkType type;

		/**
		 * Pass true to create an HTTPS link (only available for some link types); pass false to create a tg: link.
		**/
		public boolean isHttp;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 962654640;

		/**
		 * Returns an HTTPS or a tg: link with the given type. Can be called before authorization.
		 *
		 * <p> Returns {@link HttpUrl HttpUrl} </p>
		**/
		public GetInternalLink() {}

		/**
		 * Returns an HTTPS or a tg: link with the given type. Can be called before authorization.
		 *
		 * <p> Returns {@link HttpUrl HttpUrl} </p>
		 *
		 * @param type Expected type of the link.
		 * @param isHttp Pass true to create an HTTPS link (only available for some link types); pass false to create a tg: link.
		 *
		 * <p> Returns {@link HttpUrl HttpUrl} </p>
		**/
		public GetInternalLink(InternalLinkType type, boolean isHttp) {
			this.type = type;
			this.isHttp = isHttp;
		}

		/**
		 * Returns an HTTPS or a tg: link with the given type. Can be called before authorization.
		 *
		 * <p> Returns {@link HttpUrl HttpUrl} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetInternalLink(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InternalLinkTypeActiveSessions.CONSTRUCTOR: this.type = new InternalLinkTypeActiveSessions(input); break;
					case InternalLinkTypeAttachmentMenuBot.CONSTRUCTOR: this.type = new InternalLinkTypeAttachmentMenuBot(input); break;
					case InternalLinkTypeAuthenticationCode.CONSTRUCTOR: this.type = new InternalLinkTypeAuthenticationCode(input); break;
					case InternalLinkTypeBackground.CONSTRUCTOR: this.type = new InternalLinkTypeBackground(input); break;
					case InternalLinkTypeBotAddToChannel.CONSTRUCTOR: this.type = new InternalLinkTypeBotAddToChannel(input); break;
					case InternalLinkTypeBotStart.CONSTRUCTOR: this.type = new InternalLinkTypeBotStart(input); break;
					case InternalLinkTypeBotStartInGroup.CONSTRUCTOR: this.type = new InternalLinkTypeBotStartInGroup(input); break;
					case InternalLinkTypeChangePhoneNumber.CONSTRUCTOR: this.type = new InternalLinkTypeChangePhoneNumber(input); break;
					case InternalLinkTypeChatFolderInvite.CONSTRUCTOR: this.type = new InternalLinkTypeChatFolderInvite(input); break;
					case InternalLinkTypeChatFolderSettings.CONSTRUCTOR: this.type = new InternalLinkTypeChatFolderSettings(input); break;
					case InternalLinkTypeChatInvite.CONSTRUCTOR: this.type = new InternalLinkTypeChatInvite(input); break;
					case InternalLinkTypeDefaultMessageAutoDeleteTimerSettings.CONSTRUCTOR: this.type = new InternalLinkTypeDefaultMessageAutoDeleteTimerSettings(input); break;
					case InternalLinkTypeEditProfileSettings.CONSTRUCTOR: this.type = new InternalLinkTypeEditProfileSettings(input); break;
					case InternalLinkTypeGame.CONSTRUCTOR: this.type = new InternalLinkTypeGame(input); break;
					case InternalLinkTypeInstantView.CONSTRUCTOR: this.type = new InternalLinkTypeInstantView(input); break;
					case InternalLinkTypeInvoice.CONSTRUCTOR: this.type = new InternalLinkTypeInvoice(input); break;
					case InternalLinkTypeLanguagePack.CONSTRUCTOR: this.type = new InternalLinkTypeLanguagePack(input); break;
					case InternalLinkTypeLanguageSettings.CONSTRUCTOR: this.type = new InternalLinkTypeLanguageSettings(input); break;
					case InternalLinkTypeMessage.CONSTRUCTOR: this.type = new InternalLinkTypeMessage(input); break;
					case InternalLinkTypeMessageDraft.CONSTRUCTOR: this.type = new InternalLinkTypeMessageDraft(input); break;
					case InternalLinkTypePassportDataRequest.CONSTRUCTOR: this.type = new InternalLinkTypePassportDataRequest(input); break;
					case InternalLinkTypePhoneNumberConfirmation.CONSTRUCTOR: this.type = new InternalLinkTypePhoneNumberConfirmation(input); break;
					case InternalLinkTypePremiumFeatures.CONSTRUCTOR: this.type = new InternalLinkTypePremiumFeatures(input); break;
					case InternalLinkTypePrivacyAndSecuritySettings.CONSTRUCTOR: this.type = new InternalLinkTypePrivacyAndSecuritySettings(input); break;
					case InternalLinkTypeProxy.CONSTRUCTOR: this.type = new InternalLinkTypeProxy(input); break;
					case InternalLinkTypePublicChat.CONSTRUCTOR: this.type = new InternalLinkTypePublicChat(input); break;
					case InternalLinkTypeQrCodeAuthentication.CONSTRUCTOR: this.type = new InternalLinkTypeQrCodeAuthentication(input); break;
					case InternalLinkTypeRestorePurchases.CONSTRUCTOR: this.type = new InternalLinkTypeRestorePurchases(input); break;
					case InternalLinkTypeSettings.CONSTRUCTOR: this.type = new InternalLinkTypeSettings(input); break;
					case InternalLinkTypeStickerSet.CONSTRUCTOR: this.type = new InternalLinkTypeStickerSet(input); break;
					case InternalLinkTypeTheme.CONSTRUCTOR: this.type = new InternalLinkTypeTheme(input); break;
					case InternalLinkTypeThemeSettings.CONSTRUCTOR: this.type = new InternalLinkTypeThemeSettings(input); break;
					case InternalLinkTypeUnknownDeepLink.CONSTRUCTOR: this.type = new InternalLinkTypeUnknownDeepLink(input); break;
					case InternalLinkTypeUnsupportedProxy.CONSTRUCTOR: this.type = new InternalLinkTypeUnsupportedProxy(input); break;
					case InternalLinkTypeUserPhoneNumber.CONSTRUCTOR: this.type = new InternalLinkTypeUserPhoneNumber(input); break;
					case InternalLinkTypeUserToken.CONSTRUCTOR: this.type = new InternalLinkTypeUserToken(input); break;
					case InternalLinkTypeVideoChat.CONSTRUCTOR: this.type = new InternalLinkTypeVideoChat(input); break;
					case InternalLinkTypeWebApp.CONSTRUCTOR: this.type = new InternalLinkTypeWebApp(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.isHttp = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetInternalLink.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetInternalLink.CONSTRUCTOR);
			if (this.type == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.type.serialize(output);
			}
			output.writeBoolean(this.isHttp);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetInternalLink getInternalLink = (GetInternalLink) o;
			if (!Objects.equals(this.type, getInternalLink.type)) {
				return false;
			}
			if (this.isHttp != getInternalLink.isHttp) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isHttp);
			result = result * 31 + (this.type == null ? 0 : this.type.hashCode());
			return result;
		}
	}

	/**
	 * Returns information about the type of an internal link. Returns a 404
	 * error if the link is not internal. Can be called before
	 * authorization.
	 * <p> Returns {@link InternalLinkType InternalLinkType} </p>
	**/
	public static final class GetInternalLinkType extends Function<InternalLinkType> {


		/**
		 * The link.
		**/
		public String link;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1948428535;

		/**
		 * Returns information about the type of an internal link. Returns a 404 error if the link is not internal. Can be called before authorization.
		 *
		 * <p> Returns {@link InternalLinkType InternalLinkType} </p>
		**/
		public GetInternalLinkType() {}

		/**
		 * Returns information about the type of an internal link. Returns a 404 error if the link is not internal. Can be called before authorization.
		 *
		 * <p> Returns {@link InternalLinkType InternalLinkType} </p>
		 *
		 * @param link The link.
		 *
		 * <p> Returns {@link InternalLinkType InternalLinkType} </p>
		**/
		public GetInternalLinkType(String link) {
			this.link = link;
		}

		/**
		 * Returns information about the type of an internal link. Returns a 404 error if the link is not internal. Can be called before authorization.
		 *
		 * <p> Returns {@link InternalLinkType InternalLinkType} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetInternalLinkType(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] linkTmp = new byte[input.readInt()];
				input.readFully(linkTmp);
				this.link = new String(linkTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetInternalLinkType.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetInternalLinkType.CONSTRUCTOR);
			if (this.link == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] linkTmp = this.link.getBytes(StandardCharsets.UTF_8);
				output.writeInt(linkTmp.length);
				output.write(linkTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetInternalLinkType getInternalLinkType = (GetInternalLinkType) o;
			if (this.link != getInternalLinkType.link) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.link == null ? 0 : this.link.hashCode();
		}
	}

	/**
	 * Converts a JsonValue object to corresponding JSON-serialized string.
	 * Can be called synchronously.
	 * <p> Returns {@link Text Text} </p>
	**/
	public static final class GetJsonString extends Function<Text> {


		/**
		 * The JsonValue object.
		**/
		public JsonValue jsonValue;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 663458849;

		/**
		 * Converts a JsonValue object to corresponding JSON-serialized string. Can be called synchronously.
		 *
		 * <p> Returns {@link Text Text} </p>
		**/
		public GetJsonString() {}

		/**
		 * Converts a JsonValue object to corresponding JSON-serialized string. Can be called synchronously.
		 *
		 * <p> Returns {@link Text Text} </p>
		 *
		 * @param jsonValue The JsonValue object.
		 *
		 * <p> Returns {@link Text Text} </p>
		**/
		public GetJsonString(JsonValue jsonValue) {
			this.jsonValue = jsonValue;
		}

		/**
		 * Converts a JsonValue object to corresponding JSON-serialized string. Can be called synchronously.
		 *
		 * <p> Returns {@link Text Text} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetJsonString(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case JsonValueNull.CONSTRUCTOR: this.jsonValue = new JsonValueNull(input); break;
					case JsonValueBoolean.CONSTRUCTOR: this.jsonValue = new JsonValueBoolean(input); break;
					case JsonValueNumber.CONSTRUCTOR: this.jsonValue = new JsonValueNumber(input); break;
					case JsonValueString.CONSTRUCTOR: this.jsonValue = new JsonValueString(input); break;
					case JsonValueArray.CONSTRUCTOR: this.jsonValue = new JsonValueArray(input); break;
					case JsonValueObject.CONSTRUCTOR: this.jsonValue = new JsonValueObject(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetJsonString.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetJsonString.CONSTRUCTOR);
			if (this.jsonValue == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.jsonValue.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetJsonString getJsonString = (GetJsonString) o;
			if (!Objects.equals(this.jsonValue, getJsonString.jsonValue)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.jsonValue == null ? 0 : this.jsonValue.hashCode();
		}
	}

	/**
	 * Converts a JSON-serialized string to corresponding JsonValue object.
	 * Can be called synchronously.
	 * <p> Returns {@link JsonValue JsonValue} </p>
	**/
	public static final class GetJsonValue extends Function<JsonValue> {


		/**
		 * The JSON-serialized string.
		**/
		public String json;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1829086715;

		/**
		 * Converts a JSON-serialized string to corresponding JsonValue object. Can be called synchronously.
		 *
		 * <p> Returns {@link JsonValue JsonValue} </p>
		**/
		public GetJsonValue() {}

		/**
		 * Converts a JSON-serialized string to corresponding JsonValue object. Can be called synchronously.
		 *
		 * <p> Returns {@link JsonValue JsonValue} </p>
		 *
		 * @param json The JSON-serialized string.
		 *
		 * <p> Returns {@link JsonValue JsonValue} </p>
		**/
		public GetJsonValue(String json) {
			this.json = json;
		}

		/**
		 * Converts a JSON-serialized string to corresponding JsonValue object. Can be called synchronously.
		 *
		 * <p> Returns {@link JsonValue JsonValue} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetJsonValue(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] jsonTmp = new byte[input.readInt()];
				input.readFully(jsonTmp);
				this.json = new String(jsonTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetJsonValue.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetJsonValue.CONSTRUCTOR);
			if (this.json == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] jsonTmp = this.json.getBytes(StandardCharsets.UTF_8);
				output.writeInt(jsonTmp.length);
				output.write(jsonTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetJsonValue getJsonValue = (GetJsonValue) o;
			if (this.json != getJsonValue.json) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.json == null ? 0 : this.json.hashCode();
		}
	}

	/**
	 * Returns information about a language pack. Returned language pack
	 * identifier may be different from a provided one. Can be called before
	 * authorization.
	 * <p> Returns {@link LanguagePackInfo LanguagePackInfo} </p>
	**/
	public static final class GetLanguagePackInfo extends Function<LanguagePackInfo> {


		/**
		 * Language pack identifier.
		**/
		public String languagePackId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2077809320;

		/**
		 * Returns information about a language pack. Returned language pack identifier may be different from a provided one. Can be called before authorization.
		 *
		 * <p> Returns {@link LanguagePackInfo LanguagePackInfo} </p>
		**/
		public GetLanguagePackInfo() {}

		/**
		 * Returns information about a language pack. Returned language pack identifier may be different from a provided one. Can be called before authorization.
		 *
		 * <p> Returns {@link LanguagePackInfo LanguagePackInfo} </p>
		 *
		 * @param languagePackId Language pack identifier.
		 *
		 * <p> Returns {@link LanguagePackInfo LanguagePackInfo} </p>
		**/
		public GetLanguagePackInfo(String languagePackId) {
			this.languagePackId = languagePackId;
		}

		/**
		 * Returns information about a language pack. Returned language pack identifier may be different from a provided one. Can be called before authorization.
		 *
		 * <p> Returns {@link LanguagePackInfo LanguagePackInfo} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetLanguagePackInfo(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] languagePackIdTmp = new byte[input.readInt()];
				input.readFully(languagePackIdTmp);
				this.languagePackId = new String(languagePackIdTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetLanguagePackInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetLanguagePackInfo.CONSTRUCTOR);
			if (this.languagePackId == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] languagePackIdTmp = this.languagePackId.getBytes(StandardCharsets.UTF_8);
				output.writeInt(languagePackIdTmp.length);
				output.write(languagePackIdTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetLanguagePackInfo getLanguagePackInfo = (GetLanguagePackInfo) o;
			if (this.languagePackId != getLanguagePackInfo.languagePackId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.languagePackId == null ? 0 : this.languagePackId.hashCode();
		}
	}

	/**
	 * Returns a string stored in the local database from the specified
	 * localization target and language pack by its key. Returns a 404 error
	 * if the string is not found. Can be called synchronously.
	 * <p> Returns {@link LanguagePackStringValue LanguagePackStringValue}
	 * </p>
	**/
	public static final class GetLanguagePackString extends Function<LanguagePackStringValue> {


		/**
		 * Path to the language pack database in which strings are stored.
		**/
		public String languagePackDatabasePath;

		/**
		 * Localization target to which the language pack belongs.
		**/
		public String localizationTarget;

		/**
		 * Language pack identifier.
		**/
		public String languagePackId;

		/**
		 * Language pack key of the string to be returned.
		**/
		public String key;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 150789747;

		/**
		 * Returns a string stored in the local database from the specified localization target and language pack by its key. Returns a 404 error if the string is not found. Can be called synchronously.
		 *
		 * <p> Returns {@link LanguagePackStringValue LanguagePackStringValue} </p>
		**/
		public GetLanguagePackString() {}

		/**
		 * Returns a string stored in the local database from the specified localization target and language pack by its key. Returns a 404 error if the string is not found. Can be called synchronously.
		 *
		 * <p> Returns {@link LanguagePackStringValue LanguagePackStringValue} </p>
		 *
		 * @param languagePackDatabasePath Path to the language pack database in which strings are stored.
		 * @param localizationTarget Localization target to which the language pack belongs.
		 * @param languagePackId Language pack identifier.
		 * @param key Language pack key of the string to be returned.
		 *
		 * <p> Returns {@link LanguagePackStringValue LanguagePackStringValue} </p>
		**/
		public GetLanguagePackString(String languagePackDatabasePath,
				String localizationTarget,
				String languagePackId,
				String key) {
			this.languagePackDatabasePath = languagePackDatabasePath;
			this.localizationTarget = localizationTarget;
			this.languagePackId = languagePackId;
			this.key = key;
		}

		/**
		 * Returns a string stored in the local database from the specified localization target and language pack by its key. Returns a 404 error if the string is not found. Can be called synchronously.
		 *
		 * <p> Returns {@link LanguagePackStringValue LanguagePackStringValue} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetLanguagePackString(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] languagePackDatabasePathTmp = new byte[input.readInt()];
				input.readFully(languagePackDatabasePathTmp);
				this.languagePackDatabasePath = new String(languagePackDatabasePathTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] localizationTargetTmp = new byte[input.readInt()];
				input.readFully(localizationTargetTmp);
				this.localizationTarget = new String(localizationTargetTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] languagePackIdTmp = new byte[input.readInt()];
				input.readFully(languagePackIdTmp);
				this.languagePackId = new String(languagePackIdTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] keyTmp = new byte[input.readInt()];
				input.readFully(keyTmp);
				this.key = new String(keyTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetLanguagePackString.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetLanguagePackString.CONSTRUCTOR);
			if (this.languagePackDatabasePath == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] languagePackDatabasePathTmp = this.languagePackDatabasePath.getBytes(StandardCharsets.UTF_8);
				output.writeInt(languagePackDatabasePathTmp.length);
				output.write(languagePackDatabasePathTmp);
			}
			if (this.localizationTarget == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] localizationTargetTmp = this.localizationTarget.getBytes(StandardCharsets.UTF_8);
				output.writeInt(localizationTargetTmp.length);
				output.write(localizationTargetTmp);
			}
			if (this.languagePackId == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] languagePackIdTmp = this.languagePackId.getBytes(StandardCharsets.UTF_8);
				output.writeInt(languagePackIdTmp.length);
				output.write(languagePackIdTmp);
			}
			if (this.key == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] keyTmp = this.key.getBytes(StandardCharsets.UTF_8);
				output.writeInt(keyTmp.length);
				output.write(keyTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetLanguagePackString getLanguagePackString = (GetLanguagePackString) o;
			if (this.languagePackDatabasePath != getLanguagePackString.languagePackDatabasePath) {
				return false;
			}
			if (this.localizationTarget != getLanguagePackString.localizationTarget) {
				return false;
			}
			if (this.languagePackId != getLanguagePackString.languagePackId) {
				return false;
			}
			if (this.key != getLanguagePackString.key) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.languagePackDatabasePath == null ? 0 : this.languagePackDatabasePath.hashCode();
			result = result * 31 + (this.localizationTarget == null ? 0 : this.localizationTarget.hashCode());
			result = result * 31 + (this.languagePackId == null ? 0 : this.languagePackId.hashCode());
			result = result * 31 + (this.key == null ? 0 : this.key.hashCode());
			return result;
		}
	}

	/**
	 * Returns strings from a language pack in the current localization
	 * target by their keys. Can be called before authorization.
	 * <p> Returns {@link LanguagePackStrings LanguagePackStrings} </p>
	**/
	public static final class GetLanguagePackStrings extends Function<LanguagePackStrings> {


		/**
		 * Language pack identifier of the strings to be returned.
		**/
		public String languagePackId;

		/**
		 * Language pack keys of the strings to be returned; leave empty to request all available strings.
		**/
		public String[] keys;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1246259088;

		/**
		 * Returns strings from a language pack in the current localization target by their keys. Can be called before authorization.
		 *
		 * <p> Returns {@link LanguagePackStrings LanguagePackStrings} </p>
		**/
		public GetLanguagePackStrings() {}

		/**
		 * Returns strings from a language pack in the current localization target by their keys. Can be called before authorization.
		 *
		 * <p> Returns {@link LanguagePackStrings LanguagePackStrings} </p>
		 *
		 * @param languagePackId Language pack identifier of the strings to be returned.
		 * @param keys Language pack keys of the strings to be returned; leave empty to request all available strings.
		 *
		 * <p> Returns {@link LanguagePackStrings LanguagePackStrings} </p>
		**/
		public GetLanguagePackStrings(String languagePackId, String[] keys) {
			this.languagePackId = languagePackId;
			this.keys = keys;
		}

		/**
		 * Returns strings from a language pack in the current localization target by their keys. Can be called before authorization.
		 *
		 * <p> Returns {@link LanguagePackStrings LanguagePackStrings} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetLanguagePackStrings(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] languagePackIdTmp = new byte[input.readInt()];
				input.readFully(languagePackIdTmp);
				this.languagePackId = new String(languagePackIdTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				this.keys = new String[input.readInt()];
				for (int i = 0; i < this.keys.length; i++) {
					byte[] keysTmp = new byte[input.readInt()];
					input.readFully(keysTmp);
					this.keys[i] = new String(keysTmp, StandardCharsets.UTF_8);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetLanguagePackStrings.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetLanguagePackStrings.CONSTRUCTOR);
			if (this.languagePackId == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] languagePackIdTmp = this.languagePackId.getBytes(StandardCharsets.UTF_8);
				output.writeInt(languagePackIdTmp.length);
				output.write(languagePackIdTmp);
			}
			if (this.keys == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.keys.length);
				for (int i = 0; i < this.keys.length; i++) {
					byte[] keysTmp = this.keys[i].getBytes(StandardCharsets.UTF_8);
					output.writeInt(keysTmp.length);
					output.write(keysTmp);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetLanguagePackStrings getLanguagePackStrings = (GetLanguagePackStrings) o;
			if (this.languagePackId != getLanguagePackStrings.languagePackId) {
				return false;
			}
			if (!Arrays.equals(this.keys, getLanguagePackStrings.keys)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.languagePackId == null ? 0 : this.languagePackId.hashCode();
			result = result * 31 + (Arrays.hashCode(this.keys));
			return result;
		}
	}

	/**
	 * Returns information about the current localization target. This is an
	 * offline request if onlyLocal is true. Can be called before
	 * authorization.
	 * <p> Returns {@link LocalizationTargetInfo LocalizationTargetInfo} </p>
	**/
	public static final class GetLocalizationTargetInfo extends Function<LocalizationTargetInfo> {


		/**
		 * Pass true to get only locally available information without sending network requests.
		**/
		public boolean onlyLocal;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1849499526;

		/**
		 * Returns information about the current localization target. This is an offline request if onlyLocal is true. Can be called before authorization.
		 *
		 * <p> Returns {@link LocalizationTargetInfo LocalizationTargetInfo} </p>
		**/
		public GetLocalizationTargetInfo() {}

		/**
		 * Returns information about the current localization target. This is an offline request if onlyLocal is true. Can be called before authorization.
		 *
		 * <p> Returns {@link LocalizationTargetInfo LocalizationTargetInfo} </p>
		 *
		 * @param onlyLocal Pass true to get only locally available information without sending network requests.
		 *
		 * <p> Returns {@link LocalizationTargetInfo LocalizationTargetInfo} </p>
		**/
		public GetLocalizationTargetInfo(boolean onlyLocal) {
			this.onlyLocal = onlyLocal;
		}

		/**
		 * Returns information about the current localization target. This is an offline request if onlyLocal is true. Can be called before authorization.
		 *
		 * <p> Returns {@link LocalizationTargetInfo LocalizationTargetInfo} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetLocalizationTargetInfo(DataInput input) throws IOException {
			this.onlyLocal = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetLocalizationTargetInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetLocalizationTargetInfo.CONSTRUCTOR);
			output.writeBoolean(this.onlyLocal);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetLocalizationTargetInfo getLocalizationTargetInfo = (GetLocalizationTargetInfo) o;
			if (this.onlyLocal != getLocalizationTargetInfo.onlyLocal) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Boolean.hashCode(this.onlyLocal);
		}
	}

	/**
	 * Returns information about currently used log stream for internal
	 * logging of TDLib. Can be called synchronously.
	 * <p> Returns {@link LogStream LogStream} </p>
	**/
	public static final class GetLogStream extends Function<LogStream> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1167608667;

		/**
		 * Returns information about currently used log stream for internal logging of TDLib. Can be called synchronously.
		 *
		 * <p> Returns {@link LogStream LogStream} </p>
		**/
		public GetLogStream() {}

		/**
		 * Returns information about currently used log stream for internal logging of TDLib. Can be called synchronously.
		 *
		 * <p> Returns {@link LogStream LogStream} </p>
		 *
		 *
		 * <p> Returns {@link LogStream LogStream} </p>
		**/

		/**
		 * Returns information about currently used log stream for internal logging of TDLib. Can be called synchronously.
		 *
		 * <p> Returns {@link LogStream LogStream} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetLogStream(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetLogStream.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetLogStream.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return GetLogStream.CONSTRUCTOR;
		}
	}

	/**
	 * Returns current verbosity level for a specified TDLib internal log
	 * tag. Can be called synchronously.
	 * <p> Returns {@link LogVerbosityLevel LogVerbosityLevel} </p>
	**/
	public static final class GetLogTagVerbosityLevel extends Function<LogVerbosityLevel> {


		/**
		 * Logging tag to change verbosity level.
		**/
		public String tag;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 951004547;

		/**
		 * Returns current verbosity level for a specified TDLib internal log tag. Can be called synchronously.
		 *
		 * <p> Returns {@link LogVerbosityLevel LogVerbosityLevel} </p>
		**/
		public GetLogTagVerbosityLevel() {}

		/**
		 * Returns current verbosity level for a specified TDLib internal log tag. Can be called synchronously.
		 *
		 * <p> Returns {@link LogVerbosityLevel LogVerbosityLevel} </p>
		 *
		 * @param tag Logging tag to change verbosity level.
		 *
		 * <p> Returns {@link LogVerbosityLevel LogVerbosityLevel} </p>
		**/
		public GetLogTagVerbosityLevel(String tag) {
			this.tag = tag;
		}

		/**
		 * Returns current verbosity level for a specified TDLib internal log tag. Can be called synchronously.
		 *
		 * <p> Returns {@link LogVerbosityLevel LogVerbosityLevel} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetLogTagVerbosityLevel(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] tagTmp = new byte[input.readInt()];
				input.readFully(tagTmp);
				this.tag = new String(tagTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetLogTagVerbosityLevel.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetLogTagVerbosityLevel.CONSTRUCTOR);
			if (this.tag == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] tagTmp = this.tag.getBytes(StandardCharsets.UTF_8);
				output.writeInt(tagTmp.length);
				output.write(tagTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetLogTagVerbosityLevel getLogTagVerbosityLevel = (GetLogTagVerbosityLevel) o;
			if (this.tag != getLogTagVerbosityLevel.tag) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.tag == null ? 0 : this.tag.hashCode();
		}
	}

	/**
	 * Returns list of available TDLib internal log tags, for example,
	 * [&quot;actor&quot;, &quot;binlog&quot;, &quot;connections&quot;,
	 * &quot;notifications&quot;, &quot;proxy&quot;]. Can be called
	 * synchronously.
	 * <p> Returns {@link LogTags LogTags} </p>
	**/
	public static final class GetLogTags extends Function<LogTags> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -254449190;

		/**
		 * Returns list of available TDLib internal log tags, for example, [&quot;actor&quot;, &quot;binlog&quot;, &quot;connections&quot;, &quot;notifications&quot;, &quot;proxy&quot;]. Can be called synchronously.
		 *
		 * <p> Returns {@link LogTags LogTags} </p>
		**/
		public GetLogTags() {}

		/**
		 * Returns list of available TDLib internal log tags, for example, [&quot;actor&quot;, &quot;binlog&quot;, &quot;connections&quot;, &quot;notifications&quot;, &quot;proxy&quot;]. Can be called synchronously.
		 *
		 * <p> Returns {@link LogTags LogTags} </p>
		 *
		 *
		 * <p> Returns {@link LogTags LogTags} </p>
		**/

		/**
		 * Returns list of available TDLib internal log tags, for example, [&quot;actor&quot;, &quot;binlog&quot;, &quot;connections&quot;, &quot;notifications&quot;, &quot;proxy&quot;]. Can be called synchronously.
		 *
		 * <p> Returns {@link LogTags LogTags} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetLogTags(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetLogTags.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetLogTags.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return GetLogTags.CONSTRUCTOR;
		}
	}

	/**
	 * Returns current verbosity level of the internal logging of TDLib. Can
	 * be called synchronously.
	 * <p> Returns {@link LogVerbosityLevel LogVerbosityLevel} </p>
	**/
	public static final class GetLogVerbosityLevel extends Function<LogVerbosityLevel> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 594057956;

		/**
		 * Returns current verbosity level of the internal logging of TDLib. Can be called synchronously.
		 *
		 * <p> Returns {@link LogVerbosityLevel LogVerbosityLevel} </p>
		**/
		public GetLogVerbosityLevel() {}

		/**
		 * Returns current verbosity level of the internal logging of TDLib. Can be called synchronously.
		 *
		 * <p> Returns {@link LogVerbosityLevel LogVerbosityLevel} </p>
		 *
		 *
		 * <p> Returns {@link LogVerbosityLevel LogVerbosityLevel} </p>
		**/

		/**
		 * Returns current verbosity level of the internal logging of TDLib. Can be called synchronously.
		 *
		 * <p> Returns {@link LogVerbosityLevel LogVerbosityLevel} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetLogVerbosityLevel(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetLogVerbosityLevel.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetLogVerbosityLevel.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return GetLogVerbosityLevel.CONSTRUCTOR;
		}
	}

	/**
	 * Returns an HTTP URL which can be used to automatically authorize the
	 * user on a website after clicking an inline button of type
	 * inlineKeyboardButtonTypeLoginUrl. Use the method getLoginUrlInfo to
	 * find whether a prior user confirmation is needed. If an error is
	 * returned, then the button must be handled as an ordinary URL button.
	 * <p> Returns {@link HttpUrl HttpUrl} </p>
	**/
	public static final class GetLoginUrl extends Function<HttpUrl> {


		/**
		 * Chat identifier of the message with the button.
		**/
		public long chatId;

		/**
		 * Message identifier of the message with the button.
		**/
		public long messageId;

		/**
		 * Button identifier.
		**/
		public long buttonId;

		/**
		 * Pass true to allow the bot to send messages to the current user.
		**/
		public boolean allowWriteAccess;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 791844305;

		/**
		 * Returns an HTTP URL which can be used to automatically authorize the user on a website after clicking an inline button of type inlineKeyboardButtonTypeLoginUrl. Use the method getLoginUrlInfo to find whether a prior user confirmation is needed. If an error is returned, then the button must be handled as an ordinary URL button.
		 *
		 * <p> Returns {@link HttpUrl HttpUrl} </p>
		**/
		public GetLoginUrl() {}

		/**
		 * Returns an HTTP URL which can be used to automatically authorize the user on a website after clicking an inline button of type inlineKeyboardButtonTypeLoginUrl. Use the method getLoginUrlInfo to find whether a prior user confirmation is needed. If an error is returned, then the button must be handled as an ordinary URL button.
		 *
		 * <p> Returns {@link HttpUrl HttpUrl} </p>
		 *
		 * @param chatId Chat identifier of the message with the button.
		 * @param messageId Message identifier of the message with the button.
		 * @param buttonId Button identifier.
		 * @param allowWriteAccess Pass true to allow the bot to send messages to the current user.
		 *
		 * <p> Returns {@link HttpUrl HttpUrl} </p>
		**/
		public GetLoginUrl(long chatId,
				long messageId,
				long buttonId,
				boolean allowWriteAccess) {
			this.chatId = chatId;
			this.messageId = messageId;
			this.buttonId = buttonId;
			this.allowWriteAccess = allowWriteAccess;
		}

		/**
		 * Returns an HTTP URL which can be used to automatically authorize the user on a website after clicking an inline button of type inlineKeyboardButtonTypeLoginUrl. Use the method getLoginUrlInfo to find whether a prior user confirmation is needed. If an error is returned, then the button must be handled as an ordinary URL button.
		 *
		 * <p> Returns {@link HttpUrl HttpUrl} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetLoginUrl(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
			this.buttonId = input.readLong();
			this.allowWriteAccess = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetLoginUrl.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetLoginUrl.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
			output.writeLong(this.buttonId);
			output.writeBoolean(this.allowWriteAccess);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetLoginUrl getLoginUrl = (GetLoginUrl) o;
			if (this.chatId != getLoginUrl.chatId) {
				return false;
			}
			if (this.messageId != getLoginUrl.messageId) {
				return false;
			}
			if (this.buttonId != getLoginUrl.buttonId) {
				return false;
			}
			if (this.allowWriteAccess != getLoginUrl.allowWriteAccess) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Returns information about a button of type
	 * inlineKeyboardButtonTypeLoginUrl. The method needs to be called when
	 * the user presses the button.
	 * <p> Returns {@link LoginUrlInfo LoginUrlInfo} </p>
	**/
	public static final class GetLoginUrlInfo extends Function<LoginUrlInfo> {


		/**
		 * Chat identifier of the message with the button.
		**/
		public long chatId;

		/**
		 * Message identifier of the message with the button.
		**/
		public long messageId;

		/**
		 * Button identifier.
		**/
		public long buttonId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -859202125;

		/**
		 * Returns information about a button of type inlineKeyboardButtonTypeLoginUrl. The method needs to be called when the user presses the button.
		 *
		 * <p> Returns {@link LoginUrlInfo LoginUrlInfo} </p>
		**/
		public GetLoginUrlInfo() {}

		/**
		 * Returns information about a button of type inlineKeyboardButtonTypeLoginUrl. The method needs to be called when the user presses the button.
		 *
		 * <p> Returns {@link LoginUrlInfo LoginUrlInfo} </p>
		 *
		 * @param chatId Chat identifier of the message with the button.
		 * @param messageId Message identifier of the message with the button.
		 * @param buttonId Button identifier.
		 *
		 * <p> Returns {@link LoginUrlInfo LoginUrlInfo} </p>
		**/
		public GetLoginUrlInfo(long chatId, long messageId, long buttonId) {
			this.chatId = chatId;
			this.messageId = messageId;
			this.buttonId = buttonId;
		}

		/**
		 * Returns information about a button of type inlineKeyboardButtonTypeLoginUrl. The method needs to be called when the user presses the button.
		 *
		 * <p> Returns {@link LoginUrlInfo LoginUrlInfo} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetLoginUrlInfo(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
			this.buttonId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetLoginUrlInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetLoginUrlInfo.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
			output.writeLong(this.buttonId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetLoginUrlInfo getLoginUrlInfo = (GetLoginUrlInfo) o;
			if (this.chatId != getLoginUrlInfo.chatId) {
				return false;
			}
			if (this.messageId != getLoginUrlInfo.messageId) {
				return false;
			}
			if (this.buttonId != getLoginUrlInfo.buttonId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Returns information about a file with a map thumbnail in PNG format.
	 * Only map thumbnail files with size less than 1MB can be downloaded.
	 * <p> Returns {@link File File} </p>
	**/
	public static final class GetMapThumbnailFile extends Function<File> {


		/**
		 * Location of the map center.
		**/
		public Location location;

		/**
		 * Map zoom level; 13-20.
		**/
		public int zoom;

		/**
		 * Map width in pixels before applying scale; 16-1024.
		**/
		public int width;

		/**
		 * Map height in pixels before applying scale; 16-1024.
		**/
		public int height;

		/**
		 * Map scale; 1-3.
		**/
		public int scale;

		/**
		 * Identifier of a chat in which the thumbnail will be shown. Use 0 if unknown.
		**/
		public long chatId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -152660070;

		/**
		 * Returns information about a file with a map thumbnail in PNG format. Only map thumbnail files with size less than 1MB can be downloaded.
		 *
		 * <p> Returns {@link File File} </p>
		**/
		public GetMapThumbnailFile() {}

		/**
		 * Returns information about a file with a map thumbnail in PNG format. Only map thumbnail files with size less than 1MB can be downloaded.
		 *
		 * <p> Returns {@link File File} </p>
		 *
		 * @param location Location of the map center.
		 * @param zoom Map zoom level; 13-20.
		 * @param width Map width in pixels before applying scale; 16-1024.
		 * @param height Map height in pixels before applying scale; 16-1024.
		 * @param scale Map scale; 1-3.
		 * @param chatId Identifier of a chat in which the thumbnail will be shown. Use 0 if unknown.
		 *
		 * <p> Returns {@link File File} </p>
		**/
		public GetMapThumbnailFile(Location location,
				int zoom,
				int width,
				int height,
				int scale,
				long chatId) {
			this.location = location;
			this.zoom = zoom;
			this.width = width;
			this.height = height;
			this.scale = scale;
			this.chatId = chatId;
		}

		/**
		 * Returns information about a file with a map thumbnail in PNG format. Only map thumbnail files with size less than 1MB can be downloaded.
		 *
		 * <p> Returns {@link File File} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetMapThumbnailFile(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Location.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.location = new Location(input);
			}
			this.zoom = input.readInt();
			this.width = input.readInt();
			this.height = input.readInt();
			this.scale = input.readInt();
			this.chatId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetMapThumbnailFile.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetMapThumbnailFile.CONSTRUCTOR);
			if (this.location == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.location.serialize(output);
			}
			output.writeInt(this.zoom);
			output.writeInt(this.width);
			output.writeInt(this.height);
			output.writeInt(this.scale);
			output.writeLong(this.chatId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetMapThumbnailFile getMapThumbnailFile = (GetMapThumbnailFile) o;
			if (!Objects.equals(this.location, getMapThumbnailFile.location)) {
				return false;
			}
			if (this.zoom != getMapThumbnailFile.zoom) {
				return false;
			}
			if (this.width != getMapThumbnailFile.width) {
				return false;
			}
			if (this.height != getMapThumbnailFile.height) {
				return false;
			}
			if (this.scale != getMapThumbnailFile.scale) {
				return false;
			}
			if (this.chatId != getMapThumbnailFile.chatId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.zoom);
			result = result * 31 + (this.location == null ? 0 : this.location.hashCode());
			return result;
		}
	}

	/**
	 * Replaces text entities with Markdown formatting in a human-friendly
	 * format. Entities that can&#039;t be represented in Markdown
	 * unambiguously are kept as is. Can be called synchronously.
	 * <p> Returns {@link FormattedText FormattedText} </p>
	**/
	public static final class GetMarkdownText extends Function<FormattedText> {


		/**
		 * The text.
		**/
		public FormattedText text;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 164524584;

		/**
		 * Replaces text entities with Markdown formatting in a human-friendly format. Entities that can&#039;t be represented in Markdown unambiguously are kept as is. Can be called synchronously.
		 *
		 * <p> Returns {@link FormattedText FormattedText} </p>
		**/
		public GetMarkdownText() {}

		/**
		 * Replaces text entities with Markdown formatting in a human-friendly format. Entities that can&#039;t be represented in Markdown unambiguously are kept as is. Can be called synchronously.
		 *
		 * <p> Returns {@link FormattedText FormattedText} </p>
		 *
		 * @param text The text.
		 *
		 * <p> Returns {@link FormattedText FormattedText} </p>
		**/
		public GetMarkdownText(FormattedText text) {
			this.text = text;
		}

		/**
		 * Replaces text entities with Markdown formatting in a human-friendly format. Entities that can&#039;t be represented in Markdown unambiguously are kept as is. Can be called synchronously.
		 *
		 * <p> Returns {@link FormattedText FormattedText} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetMarkdownText(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (FormattedText.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.text = new FormattedText(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetMarkdownText.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetMarkdownText.CONSTRUCTOR);
			if (this.text == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.text.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetMarkdownText getMarkdownText = (GetMarkdownText) o;
			if (!Objects.equals(this.text, getMarkdownText.text)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.text == null ? 0 : this.text.hashCode();
		}
	}

	/**
	 * Returns the current user.
	 * <p> Returns {@link User User} </p>
	**/
	public static final class GetMe extends Function<User> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -191516033;

		/**
		 * Returns the current user.
		 *
		 * <p> Returns {@link User User} </p>
		**/
		public GetMe() {}

		/**
		 * Returns the current user.
		 *
		 * <p> Returns {@link User User} </p>
		 *
		 *
		 * <p> Returns {@link User User} </p>
		**/

		/**
		 * Returns the current user.
		 *
		 * <p> Returns {@link User User} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetMe(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetMe.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetMe.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return GetMe.CONSTRUCTOR;
		}
	}

	/**
	 * Returns memory statistics.
	 * <p> Returns {@link MemoryStatistics MemoryStatistics} </p>
	**/
	public static final class GetMemoryStatistics extends Function<MemoryStatistics> {


		/**
		 * Full memory statistics calculation.
		**/
		public boolean full;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2099228941;

		/**
		 * Returns memory statistics.
		 *
		 * <p> Returns {@link MemoryStatistics MemoryStatistics} </p>
		**/
		public GetMemoryStatistics() {}

		/**
		 * Returns memory statistics.
		 *
		 * <p> Returns {@link MemoryStatistics MemoryStatistics} </p>
		 *
		 * @param full Full memory statistics calculation.
		 *
		 * <p> Returns {@link MemoryStatistics MemoryStatistics} </p>
		**/
		public GetMemoryStatistics(boolean full) {
			this.full = full;
		}

		/**
		 * Returns memory statistics.
		 *
		 * <p> Returns {@link MemoryStatistics MemoryStatistics} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetMemoryStatistics(DataInput input) throws IOException {
			this.full = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetMemoryStatistics.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetMemoryStatistics.CONSTRUCTOR);
			output.writeBoolean(this.full);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetMemoryStatistics getMemoryStatistics = (GetMemoryStatistics) o;
			if (this.full != getMemoryStatistics.full) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Boolean.hashCode(this.full);
		}
	}

	/**
	 * Returns menu button set by the bot for the given user; for bots only.
	 * <p> Returns {@link BotMenuButton BotMenuButton} </p>
	**/
	public static final class GetMenuButton extends Function<BotMenuButton> {


		/**
		 * Identifier of the user or 0 to get the default menu button.
		**/
		public long userId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -437324736;

		/**
		 * Returns menu button set by the bot for the given user; for bots only.
		 *
		 * <p> Returns {@link BotMenuButton BotMenuButton} </p>
		**/
		public GetMenuButton() {}

		/**
		 * Returns menu button set by the bot for the given user; for bots only.
		 *
		 * <p> Returns {@link BotMenuButton BotMenuButton} </p>
		 *
		 * @param userId Identifier of the user or 0 to get the default menu button.
		 *
		 * <p> Returns {@link BotMenuButton BotMenuButton} </p>
		**/
		public GetMenuButton(long userId) {
			this.userId = userId;
		}

		/**
		 * Returns menu button set by the bot for the given user; for bots only.
		 *
		 * <p> Returns {@link BotMenuButton BotMenuButton} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetMenuButton(DataInput input) throws IOException {
			this.userId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetMenuButton.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetMenuButton.CONSTRUCTOR);
			output.writeLong(this.userId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetMenuButton getMenuButton = (GetMenuButton) o;
			if (this.userId != getMenuButton.userId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.userId);
		}
	}

	/**
	 * Returns information about a message.
	 * <p> Returns {@link Message Message} </p>
	**/
	public static final class GetMessage extends Function<Message> {


		/**
		 * Identifier of the chat the message belongs to.
		**/
		public long chatId;

		/**
		 * Identifier of the message to get.
		**/
		public long messageId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1821196160;

		/**
		 * Returns information about a message.
		 *
		 * <p> Returns {@link Message Message} </p>
		**/
		public GetMessage() {}

		/**
		 * Returns information about a message.
		 *
		 * <p> Returns {@link Message Message} </p>
		 *
		 * @param chatId Identifier of the chat the message belongs to.
		 * @param messageId Identifier of the message to get.
		 *
		 * <p> Returns {@link Message Message} </p>
		**/
		public GetMessage(long chatId, long messageId) {
			this.chatId = chatId;
			this.messageId = messageId;
		}

		/**
		 * Returns information about a message.
		 *
		 * <p> Returns {@link Message Message} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetMessage(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetMessage.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetMessage.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetMessage getMessage = (GetMessage) o;
			if (this.chatId != getMessage.chatId) {
				return false;
			}
			if (this.messageId != getMessage.messageId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Returns reactions added for a message, along with their sender.
	 * <p> Returns {@link AddedReactions AddedReactions} </p>
	**/
	public static final class GetMessageAddedReactions extends Function<AddedReactions> {


		/**
		 * Identifier of the chat to which the message belongs.
		**/
		public long chatId;

		/**
		 * Identifier of the message.
		**/
		public long messageId;

		/**
		 * Type of the reactions to return; pass null to return all added reactions.
		**/
		public ReactionType reactionType;

		/**
		 * Offset of the first entry to return as received from the previous request; use empty string to get the first chunk of results.
		**/
		public String offset;

		/**
		 * The maximum number of reactions to be returned; must be positive and can&#039;t be greater than 100.
		**/
		public int limit;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2110172754;

		/**
		 * Returns reactions added for a message, along with their sender.
		 *
		 * <p> Returns {@link AddedReactions AddedReactions} </p>
		**/
		public GetMessageAddedReactions() {}

		/**
		 * Returns reactions added for a message, along with their sender.
		 *
		 * <p> Returns {@link AddedReactions AddedReactions} </p>
		 *
		 * @param chatId Identifier of the chat to which the message belongs.
		 * @param messageId Identifier of the message.
		 * @param reactionType Type of the reactions to return; pass null to return all added reactions.
		 * @param offset Offset of the first entry to return as received from the previous request; use empty string to get the first chunk of results.
		 * @param limit The maximum number of reactions to be returned; must be positive and can&#039;t be greater than 100.
		 *
		 * <p> Returns {@link AddedReactions AddedReactions} </p>
		**/
		public GetMessageAddedReactions(long chatId,
				long messageId,
				ReactionType reactionType,
				String offset,
				int limit) {
			this.chatId = chatId;
			this.messageId = messageId;
			this.reactionType = reactionType;
			this.offset = offset;
			this.limit = limit;
		}

		/**
		 * Returns reactions added for a message, along with their sender.
		 *
		 * <p> Returns {@link AddedReactions AddedReactions} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetMessageAddedReactions(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ReactionTypeEmoji.CONSTRUCTOR: this.reactionType = new ReactionTypeEmoji(input); break;
					case ReactionTypeCustomEmoji.CONSTRUCTOR: this.reactionType = new ReactionTypeCustomEmoji(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				byte[] offsetTmp = new byte[input.readInt()];
				input.readFully(offsetTmp);
				this.offset = new String(offsetTmp, StandardCharsets.UTF_8);
			}
			this.limit = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetMessageAddedReactions.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetMessageAddedReactions.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
			if (this.reactionType == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.reactionType.serialize(output);
			}
			if (this.offset == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] offsetTmp = this.offset.getBytes(StandardCharsets.UTF_8);
				output.writeInt(offsetTmp.length);
				output.write(offsetTmp);
			}
			output.writeInt(this.limit);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetMessageAddedReactions getMessageAddedReactions = (GetMessageAddedReactions) o;
			if (this.chatId != getMessageAddedReactions.chatId) {
				return false;
			}
			if (this.messageId != getMessageAddedReactions.messageId) {
				return false;
			}
			if (!Objects.equals(this.reactionType, getMessageAddedReactions.reactionType)) {
				return false;
			}
			if (this.offset != getMessageAddedReactions.offset) {
				return false;
			}
			if (this.limit != getMessageAddedReactions.limit) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.reactionType == null ? 0 : this.reactionType.hashCode());
			result = result * 31 + (this.offset == null ? 0 : this.offset.hashCode());
			return result;
		}
	}

	/**
	 * Returns reactions, which can be added to a message. The list can
	 * change after updateActiveEmojiReactions, updateChatAvailableReactions
	 * for the chat, or updateMessageInteractionInfo for the message.
	 * <p> Returns {@link AvailableReactions AvailableReactions} </p>
	**/
	public static final class GetMessageAvailableReactions extends Function<AvailableReactions> {


		/**
		 * Identifier of the chat to which the message belongs.
		**/
		public long chatId;

		/**
		 * Identifier of the message.
		**/
		public long messageId;

		/**
		 * Number of reaction per row, 5-25.
		**/
		public int rowSize;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1994098354;

		/**
		 * Returns reactions, which can be added to a message. The list can change after updateActiveEmojiReactions, updateChatAvailableReactions for the chat, or updateMessageInteractionInfo for the message.
		 *
		 * <p> Returns {@link AvailableReactions AvailableReactions} </p>
		**/
		public GetMessageAvailableReactions() {}

		/**
		 * Returns reactions, which can be added to a message. The list can change after updateActiveEmojiReactions, updateChatAvailableReactions for the chat, or updateMessageInteractionInfo for the message.
		 *
		 * <p> Returns {@link AvailableReactions AvailableReactions} </p>
		 *
		 * @param chatId Identifier of the chat to which the message belongs.
		 * @param messageId Identifier of the message.
		 * @param rowSize Number of reaction per row, 5-25.
		 *
		 * <p> Returns {@link AvailableReactions AvailableReactions} </p>
		**/
		public GetMessageAvailableReactions(long chatId, long messageId, int rowSize) {
			this.chatId = chatId;
			this.messageId = messageId;
			this.rowSize = rowSize;
		}

		/**
		 * Returns reactions, which can be added to a message. The list can change after updateActiveEmojiReactions, updateChatAvailableReactions for the chat, or updateMessageInteractionInfo for the message.
		 *
		 * <p> Returns {@link AvailableReactions AvailableReactions} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetMessageAvailableReactions(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
			this.rowSize = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetMessageAvailableReactions.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetMessageAvailableReactions.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
			output.writeInt(this.rowSize);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetMessageAvailableReactions getMessageAvailableReactions = (GetMessageAvailableReactions) o;
			if (this.chatId != getMessageAvailableReactions.chatId) {
				return false;
			}
			if (this.messageId != getMessageAvailableReactions.messageId) {
				return false;
			}
			if (this.rowSize != getMessageAvailableReactions.rowSize) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Returns an HTML code for embedding the message. Available only for
	 * messages in supergroups and channels with a username.
	 * <p> Returns {@link Text Text} </p>
	**/
	public static final class GetMessageEmbeddingCode extends Function<Text> {


		/**
		 * Identifier of the chat to which the message belongs.
		**/
		public long chatId;

		/**
		 * Identifier of the message.
		**/
		public long messageId;

		/**
		 * Pass true to return an HTML code for embedding of the whole media album.
		**/
		public boolean forAlbum;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1654967561;

		/**
		 * Returns an HTML code for embedding the message. Available only for messages in supergroups and channels with a username.
		 *
		 * <p> Returns {@link Text Text} </p>
		**/
		public GetMessageEmbeddingCode() {}

		/**
		 * Returns an HTML code for embedding the message. Available only for messages in supergroups and channels with a username.
		 *
		 * <p> Returns {@link Text Text} </p>
		 *
		 * @param chatId Identifier of the chat to which the message belongs.
		 * @param messageId Identifier of the message.
		 * @param forAlbum Pass true to return an HTML code for embedding of the whole media album.
		 *
		 * <p> Returns {@link Text Text} </p>
		**/
		public GetMessageEmbeddingCode(long chatId, long messageId, boolean forAlbum) {
			this.chatId = chatId;
			this.messageId = messageId;
			this.forAlbum = forAlbum;
		}

		/**
		 * Returns an HTML code for embedding the message. Available only for messages in supergroups and channels with a username.
		 *
		 * <p> Returns {@link Text Text} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetMessageEmbeddingCode(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
			this.forAlbum = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetMessageEmbeddingCode.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetMessageEmbeddingCode.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
			output.writeBoolean(this.forAlbum);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetMessageEmbeddingCode getMessageEmbeddingCode = (GetMessageEmbeddingCode) o;
			if (this.chatId != getMessageEmbeddingCode.chatId) {
				return false;
			}
			if (this.messageId != getMessageEmbeddingCode.messageId) {
				return false;
			}
			if (this.forAlbum != getMessageEmbeddingCode.forAlbum) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Returns information about a file with messages exported from another
	 * application.
	 * <p> Returns {@link MessageFileType MessageFileType} </p>
	**/
	public static final class GetMessageFileType extends Function<MessageFileType> {


		/**
		 * Beginning of the message file; up to 100 first lines.
		**/
		public String messageFileHead;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -490270764;

		/**
		 * Returns information about a file with messages exported from another application.
		 *
		 * <p> Returns {@link MessageFileType MessageFileType} </p>
		**/
		public GetMessageFileType() {}

		/**
		 * Returns information about a file with messages exported from another application.
		 *
		 * <p> Returns {@link MessageFileType MessageFileType} </p>
		 *
		 * @param messageFileHead Beginning of the message file; up to 100 first lines.
		 *
		 * <p> Returns {@link MessageFileType MessageFileType} </p>
		**/
		public GetMessageFileType(String messageFileHead) {
			this.messageFileHead = messageFileHead;
		}

		/**
		 * Returns information about a file with messages exported from another application.
		 *
		 * <p> Returns {@link MessageFileType MessageFileType} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetMessageFileType(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] messageFileHeadTmp = new byte[input.readInt()];
				input.readFully(messageFileHeadTmp);
				this.messageFileHead = new String(messageFileHeadTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetMessageFileType.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetMessageFileType.CONSTRUCTOR);
			if (this.messageFileHead == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] messageFileHeadTmp = this.messageFileHead.getBytes(StandardCharsets.UTF_8);
				output.writeInt(messageFileHeadTmp.length);
				output.write(messageFileHeadTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetMessageFileType getMessageFileType = (GetMessageFileType) o;
			if (this.messageFileHead != getMessageFileType.messageFileHead) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.messageFileHead == null ? 0 : this.messageFileHead.hashCode();
		}
	}

	/**
	 * Returns a confirmation text to be shown to the user before starting
	 * message import.
	 * <p> Returns {@link Text Text} </p>
	**/
	public static final class GetMessageImportConfirmationText extends Function<Text> {


		/**
		 * Identifier of a chat to which the messages will be imported. It must be an identifier of a private chat with a mutual contact or an identifier of a supergroup chat with canChangeInfo administrator right.
		**/
		public long chatId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 390627752;

		/**
		 * Returns a confirmation text to be shown to the user before starting message import.
		 *
		 * <p> Returns {@link Text Text} </p>
		**/
		public GetMessageImportConfirmationText() {}

		/**
		 * Returns a confirmation text to be shown to the user before starting message import.
		 *
		 * <p> Returns {@link Text Text} </p>
		 *
		 * @param chatId Identifier of a chat to which the messages will be imported. It must be an identifier of a private chat with a mutual contact or an identifier of a supergroup chat with canChangeInfo administrator right.
		 *
		 * <p> Returns {@link Text Text} </p>
		**/
		public GetMessageImportConfirmationText(long chatId) {
			this.chatId = chatId;
		}

		/**
		 * Returns a confirmation text to be shown to the user before starting message import.
		 *
		 * <p> Returns {@link Text Text} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetMessageImportConfirmationText(DataInput input) throws IOException {
			this.chatId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetMessageImportConfirmationText.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetMessageImportConfirmationText.CONSTRUCTOR);
			output.writeLong(this.chatId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetMessageImportConfirmationText getMessageImportConfirmationText = (GetMessageImportConfirmationText) o;
			if (this.chatId != getMessageImportConfirmationText.chatId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.chatId);
		}
	}

	/**
	 * Returns an HTTPS link to a message in a chat. Available only for
	 * already sent messages in supergroups and channels, or if
	 * message.canGetMediaTimestampLinks and a media timestamp link is
	 * generated. This is an offline request.
	 * <p> Returns {@link MessageLink MessageLink} </p>
	**/
	public static final class GetMessageLink extends Function<MessageLink> {


		/**
		 * Identifier of the chat to which the message belongs.
		**/
		public long chatId;

		/**
		 * Identifier of the message.
		**/
		public long messageId;

		/**
		 * If not 0, timestamp from which the video/audio/video note/voice note playing must start, in seconds. The media can be in the message content or in its web page preview.
		**/
		public int mediaTimestamp;

		/**
		 * Pass true to create a link for the whole media album.
		**/
		public boolean forAlbum;

		/**
		 * Pass true to create a link to the message as a channel post comment, in a message thread, or a forum topic.
		**/
		public boolean inMessageThread;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -984158342;

		/**
		 * Returns an HTTPS link to a message in a chat. Available only for already sent messages in supergroups and channels, or if message.canGetMediaTimestampLinks and a media timestamp link is generated. This is an offline request.
		 *
		 * <p> Returns {@link MessageLink MessageLink} </p>
		**/
		public GetMessageLink() {}

		/**
		 * Returns an HTTPS link to a message in a chat. Available only for already sent messages in supergroups and channels, or if message.canGetMediaTimestampLinks and a media timestamp link is generated. This is an offline request.
		 *
		 * <p> Returns {@link MessageLink MessageLink} </p>
		 *
		 * @param chatId Identifier of the chat to which the message belongs.
		 * @param messageId Identifier of the message.
		 * @param mediaTimestamp If not 0, timestamp from which the video/audio/video note/voice note playing must start, in seconds. The media can be in the message content or in its web page preview.
		 * @param forAlbum Pass true to create a link for the whole media album.
		 * @param inMessageThread Pass true to create a link to the message as a channel post comment, in a message thread, or a forum topic.
		 *
		 * <p> Returns {@link MessageLink MessageLink} </p>
		**/
		public GetMessageLink(long chatId,
				long messageId,
				int mediaTimestamp,
				boolean forAlbum,
				boolean inMessageThread) {
			this.chatId = chatId;
			this.messageId = messageId;
			this.mediaTimestamp = mediaTimestamp;
			this.forAlbum = forAlbum;
			this.inMessageThread = inMessageThread;
		}

		/**
		 * Returns an HTTPS link to a message in a chat. Available only for already sent messages in supergroups and channels, or if message.canGetMediaTimestampLinks and a media timestamp link is generated. This is an offline request.
		 *
		 * <p> Returns {@link MessageLink MessageLink} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetMessageLink(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
			this.mediaTimestamp = input.readInt();
			this.forAlbum = input.readBoolean();
			this.inMessageThread = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetMessageLink.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetMessageLink.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
			output.writeInt(this.mediaTimestamp);
			output.writeBoolean(this.forAlbum);
			output.writeBoolean(this.inMessageThread);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetMessageLink getMessageLink = (GetMessageLink) o;
			if (this.chatId != getMessageLink.chatId) {
				return false;
			}
			if (this.messageId != getMessageLink.messageId) {
				return false;
			}
			if (this.mediaTimestamp != getMessageLink.mediaTimestamp) {
				return false;
			}
			if (this.forAlbum != getMessageLink.forAlbum) {
				return false;
			}
			if (this.inMessageThread != getMessageLink.inMessageThread) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Returns information about a public or private message link. Can be
	 * called for any internal link of the type internalLinkTypeMessage.
	 * <p> Returns {@link MessageLinkInfo MessageLinkInfo} </p>
	**/
	public static final class GetMessageLinkInfo extends Function<MessageLinkInfo> {


		/**
		 * The message link.
		**/
		public String url;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -700533672;

		/**
		 * Returns information about a public or private message link. Can be called for any internal link of the type internalLinkTypeMessage.
		 *
		 * <p> Returns {@link MessageLinkInfo MessageLinkInfo} </p>
		**/
		public GetMessageLinkInfo() {}

		/**
		 * Returns information about a public or private message link. Can be called for any internal link of the type internalLinkTypeMessage.
		 *
		 * <p> Returns {@link MessageLinkInfo MessageLinkInfo} </p>
		 *
		 * @param url The message link.
		 *
		 * <p> Returns {@link MessageLinkInfo MessageLinkInfo} </p>
		**/
		public GetMessageLinkInfo(String url) {
			this.url = url;
		}

		/**
		 * Returns information about a public or private message link. Can be called for any internal link of the type internalLinkTypeMessage.
		 *
		 * <p> Returns {@link MessageLinkInfo MessageLinkInfo} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetMessageLinkInfo(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] urlTmp = new byte[input.readInt()];
				input.readFully(urlTmp);
				this.url = new String(urlTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetMessageLinkInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetMessageLinkInfo.CONSTRUCTOR);
			if (this.url == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] urlTmp = this.url.getBytes(StandardCharsets.UTF_8);
				output.writeInt(urlTmp.length);
				output.write(urlTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetMessageLinkInfo getMessageLinkInfo = (GetMessageLinkInfo) o;
			if (this.url != getMessageLinkInfo.url) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.url == null ? 0 : this.url.hashCode();
		}
	}

	/**
	 * Returns information about a message, if it is available without
	 * sending network request. This is an offline request.
	 * <p> Returns {@link Message Message} </p>
	**/
	public static final class GetMessageLocally extends Function<Message> {


		/**
		 * Identifier of the chat the message belongs to.
		**/
		public long chatId;

		/**
		 * Identifier of the message to get.
		**/
		public long messageId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -603575444;

		/**
		 * Returns information about a message, if it is available without sending network request. This is an offline request.
		 *
		 * <p> Returns {@link Message Message} </p>
		**/
		public GetMessageLocally() {}

		/**
		 * Returns information about a message, if it is available without sending network request. This is an offline request.
		 *
		 * <p> Returns {@link Message Message} </p>
		 *
		 * @param chatId Identifier of the chat the message belongs to.
		 * @param messageId Identifier of the message to get.
		 *
		 * <p> Returns {@link Message Message} </p>
		**/
		public GetMessageLocally(long chatId, long messageId) {
			this.chatId = chatId;
			this.messageId = messageId;
		}

		/**
		 * Returns information about a message, if it is available without sending network request. This is an offline request.
		 *
		 * <p> Returns {@link Message Message} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetMessageLocally(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetMessageLocally.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetMessageLocally.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetMessageLocally getMessageLocally = (GetMessageLocally) o;
			if (this.chatId != getMessageLocally.chatId) {
				return false;
			}
			if (this.messageId != getMessageLocally.messageId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Returns forwarded copies of a channel message to different public
	 * channels. For optimal performance, the number of returned messages is
	 * chosen by TDLib.
	 * <p> Returns {@link FoundMessages FoundMessages} </p>
	**/
	public static final class GetMessagePublicForwards extends Function<FoundMessages> {


		/**
		 * Chat identifier of the message.
		**/
		public long chatId;

		/**
		 * Message identifier.
		**/
		public long messageId;

		/**
		 * Offset of the first entry to return as received from the previous request; use empty string to get the first chunk of results.
		**/
		public String offset;

		/**
		 * The maximum number of messages to be returned; must be positive and can&#039;t be greater than 100. For optimal performance, the number of returned messages is chosen by TDLib and can be smaller than the specified limit.
		**/
		public int limit;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1611049289;

		/**
		 * Returns forwarded copies of a channel message to different public channels. For optimal performance, the number of returned messages is chosen by TDLib.
		 *
		 * <p> Returns {@link FoundMessages FoundMessages} </p>
		**/
		public GetMessagePublicForwards() {}

		/**
		 * Returns forwarded copies of a channel message to different public channels. For optimal performance, the number of returned messages is chosen by TDLib.
		 *
		 * <p> Returns {@link FoundMessages FoundMessages} </p>
		 *
		 * @param chatId Chat identifier of the message.
		 * @param messageId Message identifier.
		 * @param offset Offset of the first entry to return as received from the previous request; use empty string to get the first chunk of results.
		 * @param limit The maximum number of messages to be returned; must be positive and can&#039;t be greater than 100. For optimal performance, the number of returned messages is chosen by TDLib and can be smaller than the specified limit.
		 *
		 * <p> Returns {@link FoundMessages FoundMessages} </p>
		**/
		public GetMessagePublicForwards(long chatId, long messageId, String offset, int limit) {
			this.chatId = chatId;
			this.messageId = messageId;
			this.offset = offset;
			this.limit = limit;
		}

		/**
		 * Returns forwarded copies of a channel message to different public channels. For optimal performance, the number of returned messages is chosen by TDLib.
		 *
		 * <p> Returns {@link FoundMessages FoundMessages} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetMessagePublicForwards(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
			if (input.readBoolean()) {
				byte[] offsetTmp = new byte[input.readInt()];
				input.readFully(offsetTmp);
				this.offset = new String(offsetTmp, StandardCharsets.UTF_8);
			}
			this.limit = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetMessagePublicForwards.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetMessagePublicForwards.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
			if (this.offset == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] offsetTmp = this.offset.getBytes(StandardCharsets.UTF_8);
				output.writeInt(offsetTmp.length);
				output.write(offsetTmp);
			}
			output.writeInt(this.limit);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetMessagePublicForwards getMessagePublicForwards = (GetMessagePublicForwards) o;
			if (this.chatId != getMessagePublicForwards.chatId) {
				return false;
			}
			if (this.messageId != getMessagePublicForwards.messageId) {
				return false;
			}
			if (this.offset != getMessagePublicForwards.offset) {
				return false;
			}
			if (this.limit != getMessagePublicForwards.limit) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.offset == null ? 0 : this.offset.hashCode());
			return result;
		}
	}

	/**
	 * Returns detailed statistics about a message. Can be used only if
	 * message.canGetStatistics == true.
	 * <p> Returns {@link MessageStatistics MessageStatistics} </p>
	**/
	public static final class GetMessageStatistics extends Function<MessageStatistics> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Message identifier.
		**/
		public long messageId;

		/**
		 * Pass true if a dark theme is used by the application.
		**/
		public boolean isDark;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1270194648;

		/**
		 * Returns detailed statistics about a message. Can be used only if message.canGetStatistics == true.
		 *
		 * <p> Returns {@link MessageStatistics MessageStatistics} </p>
		**/
		public GetMessageStatistics() {}

		/**
		 * Returns detailed statistics about a message. Can be used only if message.canGetStatistics == true.
		 *
		 * <p> Returns {@link MessageStatistics MessageStatistics} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param messageId Message identifier.
		 * @param isDark Pass true if a dark theme is used by the application.
		 *
		 * <p> Returns {@link MessageStatistics MessageStatistics} </p>
		**/
		public GetMessageStatistics(long chatId, long messageId, boolean isDark) {
			this.chatId = chatId;
			this.messageId = messageId;
			this.isDark = isDark;
		}

		/**
		 * Returns detailed statistics about a message. Can be used only if message.canGetStatistics == true.
		 *
		 * <p> Returns {@link MessageStatistics MessageStatistics} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetMessageStatistics(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
			this.isDark = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetMessageStatistics.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetMessageStatistics.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
			output.writeBoolean(this.isDark);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetMessageStatistics getMessageStatistics = (GetMessageStatistics) o;
			if (this.chatId != getMessageStatistics.chatId) {
				return false;
			}
			if (this.messageId != getMessageStatistics.messageId) {
				return false;
			}
			if (this.isDark != getMessageStatistics.isDark) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Returns information about a message thread. Can be used only if
	 * message.canGetMessageThread == true.
	 * <p> Returns {@link MessageThreadInfo MessageThreadInfo} </p>
	**/
	public static final class GetMessageThread extends Function<MessageThreadInfo> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Identifier of the message.
		**/
		public long messageId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2062695998;

		/**
		 * Returns information about a message thread. Can be used only if message.canGetMessageThread == true.
		 *
		 * <p> Returns {@link MessageThreadInfo MessageThreadInfo} </p>
		**/
		public GetMessageThread() {}

		/**
		 * Returns information about a message thread. Can be used only if message.canGetMessageThread == true.
		 *
		 * <p> Returns {@link MessageThreadInfo MessageThreadInfo} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param messageId Identifier of the message.
		 *
		 * <p> Returns {@link MessageThreadInfo MessageThreadInfo} </p>
		**/
		public GetMessageThread(long chatId, long messageId) {
			this.chatId = chatId;
			this.messageId = messageId;
		}

		/**
		 * Returns information about a message thread. Can be used only if message.canGetMessageThread == true.
		 *
		 * <p> Returns {@link MessageThreadInfo MessageThreadInfo} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetMessageThread(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetMessageThread.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetMessageThread.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetMessageThread getMessageThread = (GetMessageThread) o;
			if (this.chatId != getMessageThread.chatId) {
				return false;
			}
			if (this.messageId != getMessageThread.messageId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Returns messages in a message thread of a message. Can be used only
	 * if message.canGetMessageThread == true. Message thread of a channel
	 * message is in the channel&#039;s linked supergroup. The messages are
	 * returned in a reverse chronological order (i.e., in order of
	 * decreasing messageId). For optimal performance, the number of
	 * returned messages is chosen by TDLib.
	 * <p> Returns {@link Messages Messages} </p>
	**/
	public static final class GetMessageThreadHistory extends Function<Messages> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Message identifier, which thread history needs to be returned.
		**/
		public long messageId;

		/**
		 * Identifier of the message starting from which history must be fetched; use 0 to get results from the last message.
		**/
		public long fromMessageId;

		/**
		 * Specify 0 to get results from exactly the fromMessageId or a negative offset up to 99 to get additionally some newer messages.
		**/
		public int offset;

		/**
		 * The maximum number of messages to be returned; must be positive and can&#039;t be greater than 100. If the offset is negative, the limit must be greater than or equal to -offset. For optimal performance, the number of returned messages is chosen by TDLib and can be smaller than the specified limit.
		**/
		public int limit;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1808411608;

		/**
		 * Returns messages in a message thread of a message. Can be used only if message.canGetMessageThread == true. Message thread of a channel message is in the channel&#039;s linked supergroup. The messages are returned in a reverse chronological order (i.e., in order of decreasing messageId). For optimal performance, the number of returned messages is chosen by TDLib.
		 *
		 * <p> Returns {@link Messages Messages} </p>
		**/
		public GetMessageThreadHistory() {}

		/**
		 * Returns messages in a message thread of a message. Can be used only if message.canGetMessageThread == true. Message thread of a channel message is in the channel&#039;s linked supergroup. The messages are returned in a reverse chronological order (i.e., in order of decreasing messageId). For optimal performance, the number of returned messages is chosen by TDLib.
		 *
		 * <p> Returns {@link Messages Messages} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param messageId Message identifier, which thread history needs to be returned.
		 * @param fromMessageId Identifier of the message starting from which history must be fetched; use 0 to get results from the last message.
		 * @param offset Specify 0 to get results from exactly the fromMessageId or a negative offset up to 99 to get additionally some newer messages.
		 * @param limit The maximum number of messages to be returned; must be positive and can&#039;t be greater than 100. If the offset is negative, the limit must be greater than or equal to -offset. For optimal performance, the number of returned messages is chosen by TDLib and can be smaller than the specified limit.
		 *
		 * <p> Returns {@link Messages Messages} </p>
		**/
		public GetMessageThreadHistory(long chatId,
				long messageId,
				long fromMessageId,
				int offset,
				int limit) {
			this.chatId = chatId;
			this.messageId = messageId;
			this.fromMessageId = fromMessageId;
			this.offset = offset;
			this.limit = limit;
		}

		/**
		 * Returns messages in a message thread of a message. Can be used only if message.canGetMessageThread == true. Message thread of a channel message is in the channel&#039;s linked supergroup. The messages are returned in a reverse chronological order (i.e., in order of decreasing messageId). For optimal performance, the number of returned messages is chosen by TDLib.
		 *
		 * <p> Returns {@link Messages Messages} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetMessageThreadHistory(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
			this.fromMessageId = input.readLong();
			this.offset = input.readInt();
			this.limit = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetMessageThreadHistory.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetMessageThreadHistory.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
			output.writeLong(this.fromMessageId);
			output.writeInt(this.offset);
			output.writeInt(this.limit);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetMessageThreadHistory getMessageThreadHistory = (GetMessageThreadHistory) o;
			if (this.chatId != getMessageThreadHistory.chatId) {
				return false;
			}
			if (this.messageId != getMessageThreadHistory.messageId) {
				return false;
			}
			if (this.fromMessageId != getMessageThreadHistory.fromMessageId) {
				return false;
			}
			if (this.offset != getMessageThreadHistory.offset) {
				return false;
			}
			if (this.limit != getMessageThreadHistory.limit) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Returns viewers of a recent outgoing message in a basic group or a
	 * supergroup chat. For video notes and voice notes only users, opened
	 * content of the message, are returned. The method can be called if
	 * message.canGetViewers == true.
	 * <p> Returns {@link MessageViewers MessageViewers} </p>
	**/
	public static final class GetMessageViewers extends Function<MessageViewers> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Identifier of the message.
		**/
		public long messageId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1584457010;

		/**
		 * Returns viewers of a recent outgoing message in a basic group or a supergroup chat. For video notes and voice notes only users, opened content of the message, are returned. The method can be called if message.canGetViewers == true.
		 *
		 * <p> Returns {@link MessageViewers MessageViewers} </p>
		**/
		public GetMessageViewers() {}

		/**
		 * Returns viewers of a recent outgoing message in a basic group or a supergroup chat. For video notes and voice notes only users, opened content of the message, are returned. The method can be called if message.canGetViewers == true.
		 *
		 * <p> Returns {@link MessageViewers MessageViewers} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param messageId Identifier of the message.
		 *
		 * <p> Returns {@link MessageViewers MessageViewers} </p>
		**/
		public GetMessageViewers(long chatId, long messageId) {
			this.chatId = chatId;
			this.messageId = messageId;
		}

		/**
		 * Returns viewers of a recent outgoing message in a basic group or a supergroup chat. For video notes and voice notes only users, opened content of the message, are returned. The method can be called if message.canGetViewers == true.
		 *
		 * <p> Returns {@link MessageViewers MessageViewers} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetMessageViewers(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetMessageViewers.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetMessageViewers.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetMessageViewers getMessageViewers = (GetMessageViewers) o;
			if (this.chatId != getMessageViewers.chatId) {
				return false;
			}
			if (this.messageId != getMessageViewers.messageId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Returns information about messages. If a message is not found,
	 * returns null on the corresponding position of the result.
	 * <p> Returns {@link Messages Messages} </p>
	**/
	public static final class GetMessages extends Function<Messages> {


		/**
		 * Identifier of the chat the messages belong to.
		**/
		public long chatId;

		/**
		 * Identifiers of the messages to get.
		**/
		public long[] messageIds;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 425299338;

		/**
		 * Returns information about messages. If a message is not found, returns null on the corresponding position of the result.
		 *
		 * <p> Returns {@link Messages Messages} </p>
		**/
		public GetMessages() {}

		/**
		 * Returns information about messages. If a message is not found, returns null on the corresponding position of the result.
		 *
		 * <p> Returns {@link Messages Messages} </p>
		 *
		 * @param chatId Identifier of the chat the messages belong to.
		 * @param messageIds Identifiers of the messages to get.
		 *
		 * <p> Returns {@link Messages Messages} </p>
		**/
		public GetMessages(long chatId, long[] messageIds) {
			this.chatId = chatId;
			this.messageIds = messageIds;
		}

		/**
		 * Returns information about messages. If a message is not found, returns null on the corresponding position of the result.
		 *
		 * <p> Returns {@link Messages Messages} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetMessages(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				this.messageIds = new long[input.readInt()];
				for (int i = 0; i < this.messageIds.length; i++) {
					this.messageIds[i] = input.readLong();
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetMessages.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetMessages.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.messageIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.messageIds.length);
				for (int i = 0; i < this.messageIds.length; i++) {
					output.writeLong(this.messageIds[i]);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetMessages getMessages = (GetMessages) o;
			if (this.chatId != getMessages.chatId) {
				return false;
			}
			if (!Arrays.equals(this.messageIds, getMessages.messageIds)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (Arrays.hashCode(this.messageIds));
			return result;
		}
	}

	/**
	 * Returns network data usage statistics. Can be called before
	 * authorization.
	 * <p> Returns {@link NetworkStatistics NetworkStatistics} </p>
	**/
	public static final class GetNetworkStatistics extends Function<NetworkStatistics> {


		/**
		 * Pass true to get statistics only for the current library launch.
		**/
		public boolean onlyCurrent;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -986228706;

		/**
		 * Returns network data usage statistics. Can be called before authorization.
		 *
		 * <p> Returns {@link NetworkStatistics NetworkStatistics} </p>
		**/
		public GetNetworkStatistics() {}

		/**
		 * Returns network data usage statistics. Can be called before authorization.
		 *
		 * <p> Returns {@link NetworkStatistics NetworkStatistics} </p>
		 *
		 * @param onlyCurrent Pass true to get statistics only for the current library launch.
		 *
		 * <p> Returns {@link NetworkStatistics NetworkStatistics} </p>
		**/
		public GetNetworkStatistics(boolean onlyCurrent) {
			this.onlyCurrent = onlyCurrent;
		}

		/**
		 * Returns network data usage statistics. Can be called before authorization.
		 *
		 * <p> Returns {@link NetworkStatistics NetworkStatistics} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetNetworkStatistics(DataInput input) throws IOException {
			this.onlyCurrent = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetNetworkStatistics.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetNetworkStatistics.CONSTRUCTOR);
			output.writeBoolean(this.onlyCurrent);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetNetworkStatistics getNetworkStatistics = (GetNetworkStatistics) o;
			if (this.onlyCurrent != getNetworkStatistics.onlyCurrent) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Boolean.hashCode(this.onlyCurrent);
		}
	}

	/**
	 * Returns the value of an option by its name. (Check the list of
	 * available options on https://core.telegram.org/tdlib/options.) Can be
	 * called before authorization. Can be called synchronously for options
	 * &quot;version&quot; and &quot;commit_hash&quot;.
	 * <p> Returns {@link OptionValue OptionValue} </p>
	**/
	public static final class GetOption extends Function<OptionValue> {


		/**
		 * The name of the option.
		**/
		public String name;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1572495746;

		/**
		 * Returns the value of an option by its name. (Check the list of available options on https://core.telegram.org/tdlib/options.) Can be called before authorization. Can be called synchronously for options &quot;version&quot; and &quot;commit_hash&quot;.
		 *
		 * <p> Returns {@link OptionValue OptionValue} </p>
		**/
		public GetOption() {}

		/**
		 * Returns the value of an option by its name. (Check the list of available options on https://core.telegram.org/tdlib/options.) Can be called before authorization. Can be called synchronously for options &quot;version&quot; and &quot;commit_hash&quot;.
		 *
		 * <p> Returns {@link OptionValue OptionValue} </p>
		 *
		 * @param name The name of the option.
		 *
		 * <p> Returns {@link OptionValue OptionValue} </p>
		**/
		public GetOption(String name) {
			this.name = name;
		}

		/**
		 * Returns the value of an option by its name. (Check the list of available options on https://core.telegram.org/tdlib/options.) Can be called before authorization. Can be called synchronously for options &quot;version&quot; and &quot;commit_hash&quot;.
		 *
		 * <p> Returns {@link OptionValue OptionValue} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetOption(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] nameTmp = new byte[input.readInt()];
				input.readFully(nameTmp);
				this.name = new String(nameTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetOption.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetOption.CONSTRUCTOR);
			if (this.name == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nameTmp = this.name.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nameTmp.length);
				output.write(nameTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetOption getOption = (GetOption) o;
			if (this.name != getOption.name) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.name == null ? 0 : this.name.hashCode();
		}
	}

	/**
	 * Returns a Telegram Passport authorization form for sharing data with
	 * a service.
	 * <p> Returns {@link PassportAuthorizationForm
	 * PassportAuthorizationForm} </p>
	**/
	public static final class GetPassportAuthorizationForm extends Function<PassportAuthorizationForm> {


		/**
		 * User identifier of the service&#039;s bot.
		**/
		public long botUserId;

		/**
		 * Telegram Passport element types requested by the service.
		**/
		public String scope;

		/**
		 * Service&#039;s public key.
		**/
		public String publicKey;

		/**
		 * Unique request identifier provided by the service.
		**/
		public String nonce;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1636107398;

		/**
		 * Returns a Telegram Passport authorization form for sharing data with a service.
		 *
		 * <p> Returns {@link PassportAuthorizationForm PassportAuthorizationForm} </p>
		**/
		public GetPassportAuthorizationForm() {}

		/**
		 * Returns a Telegram Passport authorization form for sharing data with a service.
		 *
		 * <p> Returns {@link PassportAuthorizationForm PassportAuthorizationForm} </p>
		 *
		 * @param botUserId User identifier of the service&#039;s bot.
		 * @param scope Telegram Passport element types requested by the service.
		 * @param publicKey Service&#039;s public key.
		 * @param nonce Unique request identifier provided by the service.
		 *
		 * <p> Returns {@link PassportAuthorizationForm PassportAuthorizationForm} </p>
		**/
		public GetPassportAuthorizationForm(long botUserId, String scope, String publicKey, String nonce) {
			this.botUserId = botUserId;
			this.scope = scope;
			this.publicKey = publicKey;
			this.nonce = nonce;
		}

		/**
		 * Returns a Telegram Passport authorization form for sharing data with a service.
		 *
		 * <p> Returns {@link PassportAuthorizationForm PassportAuthorizationForm} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetPassportAuthorizationForm(DataInput input) throws IOException {
			this.botUserId = input.readLong();
			if (input.readBoolean()) {
				byte[] scopeTmp = new byte[input.readInt()];
				input.readFully(scopeTmp);
				this.scope = new String(scopeTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] publicKeyTmp = new byte[input.readInt()];
				input.readFully(publicKeyTmp);
				this.publicKey = new String(publicKeyTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] nonceTmp = new byte[input.readInt()];
				input.readFully(nonceTmp);
				this.nonce = new String(nonceTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetPassportAuthorizationForm.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetPassportAuthorizationForm.CONSTRUCTOR);
			output.writeLong(this.botUserId);
			if (this.scope == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] scopeTmp = this.scope.getBytes(StandardCharsets.UTF_8);
				output.writeInt(scopeTmp.length);
				output.write(scopeTmp);
			}
			if (this.publicKey == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] publicKeyTmp = this.publicKey.getBytes(StandardCharsets.UTF_8);
				output.writeInt(publicKeyTmp.length);
				output.write(publicKeyTmp);
			}
			if (this.nonce == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nonceTmp = this.nonce.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nonceTmp.length);
				output.write(nonceTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetPassportAuthorizationForm getPassportAuthorizationForm = (GetPassportAuthorizationForm) o;
			if (this.botUserId != getPassportAuthorizationForm.botUserId) {
				return false;
			}
			if (this.scope != getPassportAuthorizationForm.scope) {
				return false;
			}
			if (this.publicKey != getPassportAuthorizationForm.publicKey) {
				return false;
			}
			if (this.nonce != getPassportAuthorizationForm.nonce) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.botUserId);
			result = result * 31 + (this.scope == null ? 0 : this.scope.hashCode());
			result = result * 31 + (this.publicKey == null ? 0 : this.publicKey.hashCode());
			result = result * 31 + (this.nonce == null ? 0 : this.nonce.hashCode());
			return result;
		}
	}

	/**
	 * Returns already available Telegram Passport elements suitable for
	 * completing a Telegram Passport authorization form. Result can be
	 * received only once for each authorization form.
	 * <p> Returns {@link PassportElementsWithErrors
	 * PassportElementsWithErrors} </p>
	**/
	public static final class GetPassportAuthorizationFormAvailableElements extends Function<PassportElementsWithErrors> {


		/**
		 * Authorization form identifier.
		**/
		public int authorizationFormId;

		/**
		 * The 2-step verification password of the current user.
		**/
		public String password;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1068700924;

		/**
		 * Returns already available Telegram Passport elements suitable for completing a Telegram Passport authorization form. Result can be received only once for each authorization form.
		 *
		 * <p> Returns {@link PassportElementsWithErrors PassportElementsWithErrors} </p>
		**/
		public GetPassportAuthorizationFormAvailableElements() {}

		/**
		 * Returns already available Telegram Passport elements suitable for completing a Telegram Passport authorization form. Result can be received only once for each authorization form.
		 *
		 * <p> Returns {@link PassportElementsWithErrors PassportElementsWithErrors} </p>
		 *
		 * @param authorizationFormId Authorization form identifier.
		 * @param password The 2-step verification password of the current user.
		 *
		 * <p> Returns {@link PassportElementsWithErrors PassportElementsWithErrors} </p>
		**/
		public GetPassportAuthorizationFormAvailableElements(int authorizationFormId, String password) {
			this.authorizationFormId = authorizationFormId;
			this.password = password;
		}

		/**
		 * Returns already available Telegram Passport elements suitable for completing a Telegram Passport authorization form. Result can be received only once for each authorization form.
		 *
		 * <p> Returns {@link PassportElementsWithErrors PassportElementsWithErrors} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetPassportAuthorizationFormAvailableElements(DataInput input) throws IOException {
			this.authorizationFormId = input.readInt();
			if (input.readBoolean()) {
				byte[] passwordTmp = new byte[input.readInt()];
				input.readFully(passwordTmp);
				this.password = new String(passwordTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetPassportAuthorizationFormAvailableElements.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetPassportAuthorizationFormAvailableElements.CONSTRUCTOR);
			output.writeInt(this.authorizationFormId);
			if (this.password == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] passwordTmp = this.password.getBytes(StandardCharsets.UTF_8);
				output.writeInt(passwordTmp.length);
				output.write(passwordTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetPassportAuthorizationFormAvailableElements getPassportAuthorizationFormAvailableElements = (GetPassportAuthorizationFormAvailableElements) o;
			if (this.authorizationFormId != getPassportAuthorizationFormAvailableElements.authorizationFormId) {
				return false;
			}
			if (this.password != getPassportAuthorizationFormAvailableElements.password) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.authorizationFormId);
			result = result * 31 + (this.password == null ? 0 : this.password.hashCode());
			return result;
		}
	}

	/**
	 * Returns one of the available Telegram Passport elements.
	 * <p> Returns {@link PassportElement PassportElement} </p>
	**/
	public static final class GetPassportElement extends Function<PassportElement> {


		/**
		 * Telegram Passport element type.
		**/
		public PassportElementType type;

		/**
		 * The 2-step verification password of the current user.
		**/
		public String password;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1882398342;

		/**
		 * Returns one of the available Telegram Passport elements.
		 *
		 * <p> Returns {@link PassportElement PassportElement} </p>
		**/
		public GetPassportElement() {}

		/**
		 * Returns one of the available Telegram Passport elements.
		 *
		 * <p> Returns {@link PassportElement PassportElement} </p>
		 *
		 * @param type Telegram Passport element type.
		 * @param password The 2-step verification password of the current user.
		 *
		 * <p> Returns {@link PassportElement PassportElement} </p>
		**/
		public GetPassportElement(PassportElementType type, String password) {
			this.type = type;
			this.password = password;
		}

		/**
		 * Returns one of the available Telegram Passport elements.
		 *
		 * <p> Returns {@link PassportElement PassportElement} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetPassportElement(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case PassportElementTypePersonalDetails.CONSTRUCTOR: this.type = new PassportElementTypePersonalDetails(input); break;
					case PassportElementTypePassport.CONSTRUCTOR: this.type = new PassportElementTypePassport(input); break;
					case PassportElementTypeDriverLicense.CONSTRUCTOR: this.type = new PassportElementTypeDriverLicense(input); break;
					case PassportElementTypeIdentityCard.CONSTRUCTOR: this.type = new PassportElementTypeIdentityCard(input); break;
					case PassportElementTypeInternalPassport.CONSTRUCTOR: this.type = new PassportElementTypeInternalPassport(input); break;
					case PassportElementTypeAddress.CONSTRUCTOR: this.type = new PassportElementTypeAddress(input); break;
					case PassportElementTypeUtilityBill.CONSTRUCTOR: this.type = new PassportElementTypeUtilityBill(input); break;
					case PassportElementTypeBankStatement.CONSTRUCTOR: this.type = new PassportElementTypeBankStatement(input); break;
					case PassportElementTypeRentalAgreement.CONSTRUCTOR: this.type = new PassportElementTypeRentalAgreement(input); break;
					case PassportElementTypePassportRegistration.CONSTRUCTOR: this.type = new PassportElementTypePassportRegistration(input); break;
					case PassportElementTypeTemporaryRegistration.CONSTRUCTOR: this.type = new PassportElementTypeTemporaryRegistration(input); break;
					case PassportElementTypePhoneNumber.CONSTRUCTOR: this.type = new PassportElementTypePhoneNumber(input); break;
					case PassportElementTypeEmailAddress.CONSTRUCTOR: this.type = new PassportElementTypeEmailAddress(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				byte[] passwordTmp = new byte[input.readInt()];
				input.readFully(passwordTmp);
				this.password = new String(passwordTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetPassportElement.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetPassportElement.CONSTRUCTOR);
			if (this.type == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.type.serialize(output);
			}
			if (this.password == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] passwordTmp = this.password.getBytes(StandardCharsets.UTF_8);
				output.writeInt(passwordTmp.length);
				output.write(passwordTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetPassportElement getPassportElement = (GetPassportElement) o;
			if (!Objects.equals(this.type, getPassportElement.type)) {
				return false;
			}
			if (this.password != getPassportElement.password) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.type == null ? 0 : this.type.hashCode();
			result = result * 31 + (this.password == null ? 0 : this.password.hashCode());
			return result;
		}
	}

	/**
	 * Returns the current state of 2-step verification.
	 * <p> Returns {@link PasswordState PasswordState} </p>
	**/
	public static final class GetPasswordState extends Function<PasswordState> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -174752904;

		/**
		 * Returns the current state of 2-step verification.
		 *
		 * <p> Returns {@link PasswordState PasswordState} </p>
		**/
		public GetPasswordState() {}

		/**
		 * Returns the current state of 2-step verification.
		 *
		 * <p> Returns {@link PasswordState PasswordState} </p>
		 *
		 *
		 * <p> Returns {@link PasswordState PasswordState} </p>
		**/

		/**
		 * Returns the current state of 2-step verification.
		 *
		 * <p> Returns {@link PasswordState PasswordState} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetPasswordState(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetPasswordState.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetPasswordState.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return GetPasswordState.CONSTRUCTOR;
		}
	}

	/**
	 * Returns an invoice payment form. This method must be called when the
	 * user presses inlineKeyboardButtonBuy.
	 * <p> Returns {@link PaymentForm PaymentForm} </p>
	**/
	public static final class GetPaymentForm extends Function<PaymentForm> {


		/**
		 * The invoice.
		**/
		public InputInvoice inputInvoice;

		/**
		 * Preferred payment form theme; pass null to use the default theme.
		**/
		public ThemeParameters theme;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1924172076;

		/**
		 * Returns an invoice payment form. This method must be called when the user presses inlineKeyboardButtonBuy.
		 *
		 * <p> Returns {@link PaymentForm PaymentForm} </p>
		**/
		public GetPaymentForm() {}

		/**
		 * Returns an invoice payment form. This method must be called when the user presses inlineKeyboardButtonBuy.
		 *
		 * <p> Returns {@link PaymentForm PaymentForm} </p>
		 *
		 * @param inputInvoice The invoice.
		 * @param theme Preferred payment form theme; pass null to use the default theme.
		 *
		 * <p> Returns {@link PaymentForm PaymentForm} </p>
		**/
		public GetPaymentForm(InputInvoice inputInvoice, ThemeParameters theme) {
			this.inputInvoice = inputInvoice;
			this.theme = theme;
		}

		/**
		 * Returns an invoice payment form. This method must be called when the user presses inlineKeyboardButtonBuy.
		 *
		 * <p> Returns {@link PaymentForm PaymentForm} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetPaymentForm(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputInvoiceMessage.CONSTRUCTOR: this.inputInvoice = new InputInvoiceMessage(input); break;
					case InputInvoiceName.CONSTRUCTOR: this.inputInvoice = new InputInvoiceName(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				if (ThemeParameters.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.theme = new ThemeParameters(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetPaymentForm.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetPaymentForm.CONSTRUCTOR);
			if (this.inputInvoice == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.inputInvoice.serialize(output);
			}
			if (this.theme == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.theme.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetPaymentForm getPaymentForm = (GetPaymentForm) o;
			if (!Objects.equals(this.inputInvoice, getPaymentForm.inputInvoice)) {
				return false;
			}
			if (!Objects.equals(this.theme, getPaymentForm.theme)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.inputInvoice == null ? 0 : this.inputInvoice.hashCode();
			result = result * 31 + (this.theme == null ? 0 : this.theme.hashCode());
			return result;
		}
	}

	/**
	 * Returns information about a successful payment.
	 * <p> Returns {@link PaymentReceipt PaymentReceipt} </p>
	**/
	public static final class GetPaymentReceipt extends Function<PaymentReceipt> {


		/**
		 * Chat identifier of the messagePaymentSuccessful message.
		**/
		public long chatId;

		/**
		 * Message identifier.
		**/
		public long messageId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1013758294;

		/**
		 * Returns information about a successful payment.
		 *
		 * <p> Returns {@link PaymentReceipt PaymentReceipt} </p>
		**/
		public GetPaymentReceipt() {}

		/**
		 * Returns information about a successful payment.
		 *
		 * <p> Returns {@link PaymentReceipt PaymentReceipt} </p>
		 *
		 * @param chatId Chat identifier of the messagePaymentSuccessful message.
		 * @param messageId Message identifier.
		 *
		 * <p> Returns {@link PaymentReceipt PaymentReceipt} </p>
		**/
		public GetPaymentReceipt(long chatId, long messageId) {
			this.chatId = chatId;
			this.messageId = messageId;
		}

		/**
		 * Returns information about a successful payment.
		 *
		 * <p> Returns {@link PaymentReceipt PaymentReceipt} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetPaymentReceipt(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetPaymentReceipt.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetPaymentReceipt.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetPaymentReceipt getPaymentReceipt = (GetPaymentReceipt) o;
			if (this.chatId != getPaymentReceipt.chatId) {
				return false;
			}
			if (this.messageId != getPaymentReceipt.messageId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Returns information about a phone number by its prefix. Can be called
	 * before authorization.
	 * <p> Returns {@link PhoneNumberInfo PhoneNumberInfo} </p>
	**/
	public static final class GetPhoneNumberInfo extends Function<PhoneNumberInfo> {


		/**
		 * The phone number prefix.
		**/
		public String phoneNumberPrefix;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1608344583;

		/**
		 * Returns information about a phone number by its prefix. Can be called before authorization.
		 *
		 * <p> Returns {@link PhoneNumberInfo PhoneNumberInfo} </p>
		**/
		public GetPhoneNumberInfo() {}

		/**
		 * Returns information about a phone number by its prefix. Can be called before authorization.
		 *
		 * <p> Returns {@link PhoneNumberInfo PhoneNumberInfo} </p>
		 *
		 * @param phoneNumberPrefix The phone number prefix.
		 *
		 * <p> Returns {@link PhoneNumberInfo PhoneNumberInfo} </p>
		**/
		public GetPhoneNumberInfo(String phoneNumberPrefix) {
			this.phoneNumberPrefix = phoneNumberPrefix;
		}

		/**
		 * Returns information about a phone number by its prefix. Can be called before authorization.
		 *
		 * <p> Returns {@link PhoneNumberInfo PhoneNumberInfo} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetPhoneNumberInfo(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] phoneNumberPrefixTmp = new byte[input.readInt()];
				input.readFully(phoneNumberPrefixTmp);
				this.phoneNumberPrefix = new String(phoneNumberPrefixTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetPhoneNumberInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetPhoneNumberInfo.CONSTRUCTOR);
			if (this.phoneNumberPrefix == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] phoneNumberPrefixTmp = this.phoneNumberPrefix.getBytes(StandardCharsets.UTF_8);
				output.writeInt(phoneNumberPrefixTmp.length);
				output.write(phoneNumberPrefixTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetPhoneNumberInfo getPhoneNumberInfo = (GetPhoneNumberInfo) o;
			if (this.phoneNumberPrefix != getPhoneNumberInfo.phoneNumberPrefix) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.phoneNumberPrefix == null ? 0 : this.phoneNumberPrefix.hashCode();
		}
	}

	/**
	 * Returns information about a phone number by its prefix synchronously.
	 * getCountries must be called at least once after changing localization
	 * to the specified language if properly localized country information
	 * is expected. Can be called synchronously.
	 * <p> Returns {@link PhoneNumberInfo PhoneNumberInfo} </p>
	**/
	public static final class GetPhoneNumberInfoSync extends Function<PhoneNumberInfo> {


		/**
		 * A two-letter ISO 639-1 language code for country information localization.
		**/
		public String languageCode;

		/**
		 * The phone number prefix.
		**/
		public String phoneNumberPrefix;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 547061048;

		/**
		 * Returns information about a phone number by its prefix synchronously. getCountries must be called at least once after changing localization to the specified language if properly localized country information is expected. Can be called synchronously.
		 *
		 * <p> Returns {@link PhoneNumberInfo PhoneNumberInfo} </p>
		**/
		public GetPhoneNumberInfoSync() {}

		/**
		 * Returns information about a phone number by its prefix synchronously. getCountries must be called at least once after changing localization to the specified language if properly localized country information is expected. Can be called synchronously.
		 *
		 * <p> Returns {@link PhoneNumberInfo PhoneNumberInfo} </p>
		 *
		 * @param languageCode A two-letter ISO 639-1 language code for country information localization.
		 * @param phoneNumberPrefix The phone number prefix.
		 *
		 * <p> Returns {@link PhoneNumberInfo PhoneNumberInfo} </p>
		**/
		public GetPhoneNumberInfoSync(String languageCode, String phoneNumberPrefix) {
			this.languageCode = languageCode;
			this.phoneNumberPrefix = phoneNumberPrefix;
		}

		/**
		 * Returns information about a phone number by its prefix synchronously. getCountries must be called at least once after changing localization to the specified language if properly localized country information is expected. Can be called synchronously.
		 *
		 * <p> Returns {@link PhoneNumberInfo PhoneNumberInfo} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetPhoneNumberInfoSync(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] languageCodeTmp = new byte[input.readInt()];
				input.readFully(languageCodeTmp);
				this.languageCode = new String(languageCodeTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] phoneNumberPrefixTmp = new byte[input.readInt()];
				input.readFully(phoneNumberPrefixTmp);
				this.phoneNumberPrefix = new String(phoneNumberPrefixTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetPhoneNumberInfoSync.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetPhoneNumberInfoSync.CONSTRUCTOR);
			if (this.languageCode == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] languageCodeTmp = this.languageCode.getBytes(StandardCharsets.UTF_8);
				output.writeInt(languageCodeTmp.length);
				output.write(languageCodeTmp);
			}
			if (this.phoneNumberPrefix == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] phoneNumberPrefixTmp = this.phoneNumberPrefix.getBytes(StandardCharsets.UTF_8);
				output.writeInt(phoneNumberPrefixTmp.length);
				output.write(phoneNumberPrefixTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetPhoneNumberInfoSync getPhoneNumberInfoSync = (GetPhoneNumberInfoSync) o;
			if (this.languageCode != getPhoneNumberInfoSync.languageCode) {
				return false;
			}
			if (this.phoneNumberPrefix != getPhoneNumberInfoSync.phoneNumberPrefix) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.languageCode == null ? 0 : this.languageCode.hashCode();
			result = result * 31 + (this.phoneNumberPrefix == null ? 0 : this.phoneNumberPrefix.hashCode());
			return result;
		}
	}

	/**
	 * Returns users voted for the specified option in a non-anonymous
	 * polls. For optimal performance, the number of returned users is
	 * chosen by TDLib.
	 * <p> Returns {@link Users Users} </p>
	**/
	public static final class GetPollVoters extends Function<Users> {


		/**
		 * Identifier of the chat to which the poll belongs.
		**/
		public long chatId;

		/**
		 * Identifier of the message containing the poll.
		**/
		public long messageId;

		/**
		 * 0-based identifier of the answer option.
		**/
		public int optionId;

		/**
		 * Number of users to skip in the result; must be non-negative.
		**/
		public int offset;

		/**
		 * The maximum number of users to be returned; must be positive and can&#039;t be greater than 50. For optimal performance, the number of returned users is chosen by TDLib and can be smaller than the specified limit, even if the end of the voter list has not been reached.
		**/
		public int limit;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2075288734;

		/**
		 * Returns users voted for the specified option in a non-anonymous polls. For optimal performance, the number of returned users is chosen by TDLib.
		 *
		 * <p> Returns {@link Users Users} </p>
		**/
		public GetPollVoters() {}

		/**
		 * Returns users voted for the specified option in a non-anonymous polls. For optimal performance, the number of returned users is chosen by TDLib.
		 *
		 * <p> Returns {@link Users Users} </p>
		 *
		 * @param chatId Identifier of the chat to which the poll belongs.
		 * @param messageId Identifier of the message containing the poll.
		 * @param optionId 0-based identifier of the answer option.
		 * @param offset Number of users to skip in the result; must be non-negative.
		 * @param limit The maximum number of users to be returned; must be positive and can&#039;t be greater than 50. For optimal performance, the number of returned users is chosen by TDLib and can be smaller than the specified limit, even if the end of the voter list has not been reached.
		 *
		 * <p> Returns {@link Users Users} </p>
		**/
		public GetPollVoters(long chatId,
				long messageId,
				int optionId,
				int offset,
				int limit) {
			this.chatId = chatId;
			this.messageId = messageId;
			this.optionId = optionId;
			this.offset = offset;
			this.limit = limit;
		}

		/**
		 * Returns users voted for the specified option in a non-anonymous polls. For optimal performance, the number of returned users is chosen by TDLib.
		 *
		 * <p> Returns {@link Users Users} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetPollVoters(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
			this.optionId = input.readInt();
			this.offset = input.readInt();
			this.limit = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetPollVoters.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetPollVoters.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
			output.writeInt(this.optionId);
			output.writeInt(this.offset);
			output.writeInt(this.limit);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetPollVoters getPollVoters = (GetPollVoters) o;
			if (this.chatId != getPollVoters.chatId) {
				return false;
			}
			if (this.messageId != getPollVoters.messageId) {
				return false;
			}
			if (this.optionId != getPollVoters.optionId) {
				return false;
			}
			if (this.offset != getPollVoters.offset) {
				return false;
			}
			if (this.limit != getPollVoters.limit) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Returns an IETF language tag of the language preferred in the
	 * country, which must be used to fill native fields in Telegram
	 * Passport personal details. Returns a 404 error if unknown.
	 * <p> Returns {@link Text Text} </p>
	**/
	public static final class GetPreferredCountryLanguage extends Function<Text> {


		/**
		 * A two-letter ISO 3166-1 alpha-2 country code.
		**/
		public String countryCode;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -933049386;

		/**
		 * Returns an IETF language tag of the language preferred in the country, which must be used to fill native fields in Telegram Passport personal details. Returns a 404 error if unknown.
		 *
		 * <p> Returns {@link Text Text} </p>
		**/
		public GetPreferredCountryLanguage() {}

		/**
		 * Returns an IETF language tag of the language preferred in the country, which must be used to fill native fields in Telegram Passport personal details. Returns a 404 error if unknown.
		 *
		 * <p> Returns {@link Text Text} </p>
		 *
		 * @param countryCode A two-letter ISO 3166-1 alpha-2 country code.
		 *
		 * <p> Returns {@link Text Text} </p>
		**/
		public GetPreferredCountryLanguage(String countryCode) {
			this.countryCode = countryCode;
		}

		/**
		 * Returns an IETF language tag of the language preferred in the country, which must be used to fill native fields in Telegram Passport personal details. Returns a 404 error if unknown.
		 *
		 * <p> Returns {@link Text Text} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetPreferredCountryLanguage(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] countryCodeTmp = new byte[input.readInt()];
				input.readFully(countryCodeTmp);
				this.countryCode = new String(countryCodeTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetPreferredCountryLanguage.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetPreferredCountryLanguage.CONSTRUCTOR);
			if (this.countryCode == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] countryCodeTmp = this.countryCode.getBytes(StandardCharsets.UTF_8);
				output.writeInt(countryCodeTmp.length);
				output.write(countryCodeTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetPreferredCountryLanguage getPreferredCountryLanguage = (GetPreferredCountryLanguage) o;
			if (this.countryCode != getPreferredCountryLanguage.countryCode) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.countryCode == null ? 0 : this.countryCode.hashCode();
		}
	}

	/**
	 * Returns information about features, available to Premium users.
	 * <p> Returns {@link PremiumFeatures PremiumFeatures} </p>
	**/
	public static final class GetPremiumFeatures extends Function<PremiumFeatures> {


		/**
		 * Source of the request; pass null if the method is called from some non-standard source.
		**/
		public PremiumSource source;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1260640695;

		/**
		 * Returns information about features, available to Premium users.
		 *
		 * <p> Returns {@link PremiumFeatures PremiumFeatures} </p>
		**/
		public GetPremiumFeatures() {}

		/**
		 * Returns information about features, available to Premium users.
		 *
		 * <p> Returns {@link PremiumFeatures PremiumFeatures} </p>
		 *
		 * @param source Source of the request; pass null if the method is called from some non-standard source.
		 *
		 * <p> Returns {@link PremiumFeatures PremiumFeatures} </p>
		**/
		public GetPremiumFeatures(PremiumSource source) {
			this.source = source;
		}

		/**
		 * Returns information about features, available to Premium users.
		 *
		 * <p> Returns {@link PremiumFeatures PremiumFeatures} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetPremiumFeatures(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case PremiumSourceLimitExceeded.CONSTRUCTOR: this.source = new PremiumSourceLimitExceeded(input); break;
					case PremiumSourceFeature.CONSTRUCTOR: this.source = new PremiumSourceFeature(input); break;
					case PremiumSourceLink.CONSTRUCTOR: this.source = new PremiumSourceLink(input); break;
					case PremiumSourceSettings.CONSTRUCTOR: this.source = new PremiumSourceSettings(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetPremiumFeatures.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetPremiumFeatures.CONSTRUCTOR);
			if (this.source == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.source.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetPremiumFeatures getPremiumFeatures = (GetPremiumFeatures) o;
			if (!Objects.equals(this.source, getPremiumFeatures.source)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.source == null ? 0 : this.source.hashCode();
		}
	}

	/**
	 * Returns information about a limit, increased for Premium users.
	 * Returns a 404 error if the limit is unknown.
	 * <p> Returns {@link PremiumLimit PremiumLimit} </p>
	**/
	public static final class GetPremiumLimit extends Function<PremiumLimit> {


		/**
		 * Type of the limit.
		**/
		public PremiumLimitType limitType;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1075313898;

		/**
		 * Returns information about a limit, increased for Premium users. Returns a 404 error if the limit is unknown.
		 *
		 * <p> Returns {@link PremiumLimit PremiumLimit} </p>
		**/
		public GetPremiumLimit() {}

		/**
		 * Returns information about a limit, increased for Premium users. Returns a 404 error if the limit is unknown.
		 *
		 * <p> Returns {@link PremiumLimit PremiumLimit} </p>
		 *
		 * @param limitType Type of the limit.
		 *
		 * <p> Returns {@link PremiumLimit PremiumLimit} </p>
		**/
		public GetPremiumLimit(PremiumLimitType limitType) {
			this.limitType = limitType;
		}

		/**
		 * Returns information about a limit, increased for Premium users. Returns a 404 error if the limit is unknown.
		 *
		 * <p> Returns {@link PremiumLimit PremiumLimit} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetPremiumLimit(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case PremiumLimitTypeSupergroupCount.CONSTRUCTOR: this.limitType = new PremiumLimitTypeSupergroupCount(input); break;
					case PremiumLimitTypePinnedChatCount.CONSTRUCTOR: this.limitType = new PremiumLimitTypePinnedChatCount(input); break;
					case PremiumLimitTypeCreatedPublicChatCount.CONSTRUCTOR: this.limitType = new PremiumLimitTypeCreatedPublicChatCount(input); break;
					case PremiumLimitTypeSavedAnimationCount.CONSTRUCTOR: this.limitType = new PremiumLimitTypeSavedAnimationCount(input); break;
					case PremiumLimitTypeFavoriteStickerCount.CONSTRUCTOR: this.limitType = new PremiumLimitTypeFavoriteStickerCount(input); break;
					case PremiumLimitTypeChatFolderCount.CONSTRUCTOR: this.limitType = new PremiumLimitTypeChatFolderCount(input); break;
					case PremiumLimitTypeChatFolderChosenChatCount.CONSTRUCTOR: this.limitType = new PremiumLimitTypeChatFolderChosenChatCount(input); break;
					case PremiumLimitTypePinnedArchivedChatCount.CONSTRUCTOR: this.limitType = new PremiumLimitTypePinnedArchivedChatCount(input); break;
					case PremiumLimitTypeCaptionLength.CONSTRUCTOR: this.limitType = new PremiumLimitTypeCaptionLength(input); break;
					case PremiumLimitTypeBioLength.CONSTRUCTOR: this.limitType = new PremiumLimitTypeBioLength(input); break;
					case PremiumLimitTypeChatFolderInviteLinkCount.CONSTRUCTOR: this.limitType = new PremiumLimitTypeChatFolderInviteLinkCount(input); break;
					case PremiumLimitTypeShareableChatFolderCount.CONSTRUCTOR: this.limitType = new PremiumLimitTypeShareableChatFolderCount(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetPremiumLimit.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetPremiumLimit.CONSTRUCTOR);
			if (this.limitType == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.limitType.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetPremiumLimit getPremiumLimit = (GetPremiumLimit) o;
			if (!Objects.equals(this.limitType, getPremiumLimit.limitType)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.limitType == null ? 0 : this.limitType.hashCode();
		}
	}

	/**
	 * Returns state of Telegram Premium subscription and promotion videos
	 * for Premium features.
	 * <p> Returns {@link PremiumState PremiumState} </p>
	**/
	public static final class GetPremiumState extends Function<PremiumState> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 663632610;

		/**
		 * Returns state of Telegram Premium subscription and promotion videos for Premium features.
		 *
		 * <p> Returns {@link PremiumState PremiumState} </p>
		**/
		public GetPremiumState() {}

		/**
		 * Returns state of Telegram Premium subscription and promotion videos for Premium features.
		 *
		 * <p> Returns {@link PremiumState PremiumState} </p>
		 *
		 *
		 * <p> Returns {@link PremiumState PremiumState} </p>
		**/

		/**
		 * Returns state of Telegram Premium subscription and promotion videos for Premium features.
		 *
		 * <p> Returns {@link PremiumState PremiumState} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetPremiumState(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetPremiumState.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetPremiumState.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return GetPremiumState.CONSTRUCTOR;
		}
	}

	/**
	 * Returns examples of premium stickers for demonstration purposes.
	 * <p> Returns {@link Stickers Stickers} </p>
	**/
	public static final class GetPremiumStickerExamples extends Function<Stickers> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1399442328;

		/**
		 * Returns examples of premium stickers for demonstration purposes.
		 *
		 * <p> Returns {@link Stickers Stickers} </p>
		**/
		public GetPremiumStickerExamples() {}

		/**
		 * Returns examples of premium stickers for demonstration purposes.
		 *
		 * <p> Returns {@link Stickers Stickers} </p>
		 *
		 *
		 * <p> Returns {@link Stickers Stickers} </p>
		**/

		/**
		 * Returns examples of premium stickers for demonstration purposes.
		 *
		 * <p> Returns {@link Stickers Stickers} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetPremiumStickerExamples(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetPremiumStickerExamples.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetPremiumStickerExamples.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return GetPremiumStickerExamples.CONSTRUCTOR;
		}
	}

	/**
	 * Returns premium stickers from regular sticker sets.
	 * <p> Returns {@link Stickers Stickers} </p>
	**/
	public static final class GetPremiumStickers extends Function<Stickers> {


		/**
		 * The maximum number of stickers to be returned; 0-100.
		**/
		public int limit;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -280950192;

		/**
		 * Returns premium stickers from regular sticker sets.
		 *
		 * <p> Returns {@link Stickers Stickers} </p>
		**/
		public GetPremiumStickers() {}

		/**
		 * Returns premium stickers from regular sticker sets.
		 *
		 * <p> Returns {@link Stickers Stickers} </p>
		 *
		 * @param limit The maximum number of stickers to be returned; 0-100.
		 *
		 * <p> Returns {@link Stickers Stickers} </p>
		**/
		public GetPremiumStickers(int limit) {
			this.limit = limit;
		}

		/**
		 * Returns premium stickers from regular sticker sets.
		 *
		 * <p> Returns {@link Stickers Stickers} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetPremiumStickers(DataInput input) throws IOException {
			this.limit = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetPremiumStickers.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetPremiumStickers.CONSTRUCTOR);
			output.writeInt(this.limit);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetPremiumStickers getPremiumStickers = (GetPremiumStickers) o;
			if (this.limit != getPremiumStickers.limit) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.limit);
		}
	}

	/**
	 * Returns list of proxies that are currently set up. Can be called
	 * before authorization.
	 * <p> Returns {@link Proxies Proxies} </p>
	**/
	public static final class GetProxies extends Function<Proxies> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -95026381;

		/**
		 * Returns list of proxies that are currently set up. Can be called before authorization.
		 *
		 * <p> Returns {@link Proxies Proxies} </p>
		**/
		public GetProxies() {}

		/**
		 * Returns list of proxies that are currently set up. Can be called before authorization.
		 *
		 * <p> Returns {@link Proxies Proxies} </p>
		 *
		 *
		 * <p> Returns {@link Proxies Proxies} </p>
		**/

		/**
		 * Returns list of proxies that are currently set up. Can be called before authorization.
		 *
		 * <p> Returns {@link Proxies Proxies} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetProxies(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetProxies.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetProxies.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return GetProxies.CONSTRUCTOR;
		}
	}

	/**
	 * Returns an HTTPS link, which can be used to add a proxy. Available
	 * only for SOCKS5 and MTProto proxies. Can be called before
	 * authorization.
	 * <p> Returns {@link HttpUrl HttpUrl} </p>
	**/
	public static final class GetProxyLink extends Function<HttpUrl> {


		/**
		 * Proxy identifier.
		**/
		public int proxyId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1054495112;

		/**
		 * Returns an HTTPS link, which can be used to add a proxy. Available only for SOCKS5 and MTProto proxies. Can be called before authorization.
		 *
		 * <p> Returns {@link HttpUrl HttpUrl} </p>
		**/
		public GetProxyLink() {}

		/**
		 * Returns an HTTPS link, which can be used to add a proxy. Available only for SOCKS5 and MTProto proxies. Can be called before authorization.
		 *
		 * <p> Returns {@link HttpUrl HttpUrl} </p>
		 *
		 * @param proxyId Proxy identifier.
		 *
		 * <p> Returns {@link HttpUrl HttpUrl} </p>
		**/
		public GetProxyLink(int proxyId) {
			this.proxyId = proxyId;
		}

		/**
		 * Returns an HTTPS link, which can be used to add a proxy. Available only for SOCKS5 and MTProto proxies. Can be called before authorization.
		 *
		 * <p> Returns {@link HttpUrl HttpUrl} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetProxyLink(DataInput input) throws IOException {
			this.proxyId = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetProxyLink.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetProxyLink.CONSTRUCTOR);
			output.writeInt(this.proxyId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetProxyLink getProxyLink = (GetProxyLink) o;
			if (this.proxyId != getProxyLink.proxyId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.proxyId);
		}
	}

	/**
	 * Returns a globally unique push notification subscription identifier
	 * for identification of an account, which has received a push
	 * notification. Can be called synchronously.
	 * <p> Returns {@link PushReceiverId PushReceiverId} </p>
	**/
	public static final class GetPushReceiverId extends Function<PushReceiverId> {


		/**
		 * JSON-encoded push notification payload.
		**/
		public String payload;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -286505294;

		/**
		 * Returns a globally unique push notification subscription identifier for identification of an account, which has received a push notification. Can be called synchronously.
		 *
		 * <p> Returns {@link PushReceiverId PushReceiverId} </p>
		**/
		public GetPushReceiverId() {}

		/**
		 * Returns a globally unique push notification subscription identifier for identification of an account, which has received a push notification. Can be called synchronously.
		 *
		 * <p> Returns {@link PushReceiverId PushReceiverId} </p>
		 *
		 * @param payload JSON-encoded push notification payload.
		 *
		 * <p> Returns {@link PushReceiverId PushReceiverId} </p>
		**/
		public GetPushReceiverId(String payload) {
			this.payload = payload;
		}

		/**
		 * Returns a globally unique push notification subscription identifier for identification of an account, which has received a push notification. Can be called synchronously.
		 *
		 * <p> Returns {@link PushReceiverId PushReceiverId} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetPushReceiverId(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] payloadTmp = new byte[input.readInt()];
				input.readFully(payloadTmp);
				this.payload = new String(payloadTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetPushReceiverId.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetPushReceiverId.CONSTRUCTOR);
			if (this.payload == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] payloadTmp = this.payload.getBytes(StandardCharsets.UTF_8);
				output.writeInt(payloadTmp.length);
				output.write(payloadTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetPushReceiverId getPushReceiverId = (GetPushReceiverId) o;
			if (this.payload != getPushReceiverId.payload) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.payload == null ? 0 : this.payload.hashCode();
		}
	}

	/**
	 * Returns recent emoji statuses.
	 * <p> Returns {@link EmojiStatuses EmojiStatuses} </p>
	**/
	public static final class GetRecentEmojiStatuses extends Function<EmojiStatuses> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1371914967;

		/**
		 * Returns recent emoji statuses.
		 *
		 * <p> Returns {@link EmojiStatuses EmojiStatuses} </p>
		**/
		public GetRecentEmojiStatuses() {}

		/**
		 * Returns recent emoji statuses.
		 *
		 * <p> Returns {@link EmojiStatuses EmojiStatuses} </p>
		 *
		 *
		 * <p> Returns {@link EmojiStatuses EmojiStatuses} </p>
		**/

		/**
		 * Returns recent emoji statuses.
		 *
		 * <p> Returns {@link EmojiStatuses EmojiStatuses} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetRecentEmojiStatuses(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetRecentEmojiStatuses.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetRecentEmojiStatuses.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return GetRecentEmojiStatuses.CONSTRUCTOR;
		}
	}

	/**
	 * Returns up to 20 recently used inline bots in the order of their last
	 * usage.
	 * <p> Returns {@link Users Users} </p>
	**/
	public static final class GetRecentInlineBots extends Function<Users> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1437823548;

		/**
		 * Returns up to 20 recently used inline bots in the order of their last usage.
		 *
		 * <p> Returns {@link Users Users} </p>
		**/
		public GetRecentInlineBots() {}

		/**
		 * Returns up to 20 recently used inline bots in the order of their last usage.
		 *
		 * <p> Returns {@link Users Users} </p>
		 *
		 *
		 * <p> Returns {@link Users Users} </p>
		**/

		/**
		 * Returns up to 20 recently used inline bots in the order of their last usage.
		 *
		 * <p> Returns {@link Users Users} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetRecentInlineBots(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetRecentInlineBots.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetRecentInlineBots.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return GetRecentInlineBots.CONSTRUCTOR;
		}
	}

	/**
	 * Returns a list of recently used stickers.
	 * <p> Returns {@link Stickers Stickers} </p>
	**/
	public static final class GetRecentStickers extends Function<Stickers> {


		/**
		 * Pass true to return stickers and masks that were recently attached to photos or video files; pass false to return recently sent stickers.
		**/
		public boolean isAttached;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -579622241;

		/**
		 * Returns a list of recently used stickers.
		 *
		 * <p> Returns {@link Stickers Stickers} </p>
		**/
		public GetRecentStickers() {}

		/**
		 * Returns a list of recently used stickers.
		 *
		 * <p> Returns {@link Stickers Stickers} </p>
		 *
		 * @param isAttached Pass true to return stickers and masks that were recently attached to photos or video files; pass false to return recently sent stickers.
		 *
		 * <p> Returns {@link Stickers Stickers} </p>
		**/
		public GetRecentStickers(boolean isAttached) {
			this.isAttached = isAttached;
		}

		/**
		 * Returns a list of recently used stickers.
		 *
		 * <p> Returns {@link Stickers Stickers} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetRecentStickers(DataInput input) throws IOException {
			this.isAttached = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetRecentStickers.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetRecentStickers.CONSTRUCTOR);
			output.writeBoolean(this.isAttached);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetRecentStickers getRecentStickers = (GetRecentStickers) o;
			if (this.isAttached != getRecentStickers.isAttached) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Boolean.hashCode(this.isAttached);
		}
	}

	/**
	 * Returns recently opened chats, this is an offline request. Returns
	 * chats in the order of last opening.
	 * <p> Returns {@link Chats Chats} </p>
	**/
	public static final class GetRecentlyOpenedChats extends Function<Chats> {


		/**
		 * The maximum number of chats to be returned.
		**/
		public int limit;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1924156893;

		/**
		 * Returns recently opened chats, this is an offline request. Returns chats in the order of last opening.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		**/
		public GetRecentlyOpenedChats() {}

		/**
		 * Returns recently opened chats, this is an offline request. Returns chats in the order of last opening.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		 *
		 * @param limit The maximum number of chats to be returned.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		**/
		public GetRecentlyOpenedChats(int limit) {
			this.limit = limit;
		}

		/**
		 * Returns recently opened chats, this is an offline request. Returns chats in the order of last opening.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetRecentlyOpenedChats(DataInput input) throws IOException {
			this.limit = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetRecentlyOpenedChats.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetRecentlyOpenedChats.CONSTRUCTOR);
			output.writeInt(this.limit);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetRecentlyOpenedChats getRecentlyOpenedChats = (GetRecentlyOpenedChats) o;
			if (this.limit != getRecentlyOpenedChats.limit) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.limit);
		}
	}

	/**
	 * Returns t.me URLs recently visited by a newly registered user.
	 * <p> Returns {@link TMeUrls TMeUrls} </p>
	**/
	public static final class GetRecentlyVisitedTMeUrls extends Function<TMeUrls> {


		/**
		 * Google Play referrer to identify the user.
		**/
		public String referrer;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 806754961;

		/**
		 * Returns t.me URLs recently visited by a newly registered user.
		 *
		 * <p> Returns {@link TMeUrls TMeUrls} </p>
		**/
		public GetRecentlyVisitedTMeUrls() {}

		/**
		 * Returns t.me URLs recently visited by a newly registered user.
		 *
		 * <p> Returns {@link TMeUrls TMeUrls} </p>
		 *
		 * @param referrer Google Play referrer to identify the user.
		 *
		 * <p> Returns {@link TMeUrls TMeUrls} </p>
		**/
		public GetRecentlyVisitedTMeUrls(String referrer) {
			this.referrer = referrer;
		}

		/**
		 * Returns t.me URLs recently visited by a newly registered user.
		 *
		 * <p> Returns {@link TMeUrls TMeUrls} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetRecentlyVisitedTMeUrls(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] referrerTmp = new byte[input.readInt()];
				input.readFully(referrerTmp);
				this.referrer = new String(referrerTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetRecentlyVisitedTMeUrls.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetRecentlyVisitedTMeUrls.CONSTRUCTOR);
			if (this.referrer == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] referrerTmp = this.referrer.getBytes(StandardCharsets.UTF_8);
				output.writeInt(referrerTmp.length);
				output.write(referrerTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetRecentlyVisitedTMeUrls getRecentlyVisitedTMeUrls = (GetRecentlyVisitedTMeUrls) o;
			if (this.referrer != getRecentlyVisitedTMeUrls.referrer) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.referrer == null ? 0 : this.referrer.hashCode();
		}
	}

	/**
	 * Returns recommended chat folders for the current user.
	 * <p> Returns {@link RecommendedChatFolders RecommendedChatFolders} </p>
	**/
	public static final class GetRecommendedChatFolders extends Function<RecommendedChatFolders> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -145540217;

		/**
		 * Returns recommended chat folders for the current user.
		 *
		 * <p> Returns {@link RecommendedChatFolders RecommendedChatFolders} </p>
		**/
		public GetRecommendedChatFolders() {}

		/**
		 * Returns recommended chat folders for the current user.
		 *
		 * <p> Returns {@link RecommendedChatFolders RecommendedChatFolders} </p>
		 *
		 *
		 * <p> Returns {@link RecommendedChatFolders RecommendedChatFolders} </p>
		**/

		/**
		 * Returns recommended chat folders for the current user.
		 *
		 * <p> Returns {@link RecommendedChatFolders RecommendedChatFolders} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetRecommendedChatFolders(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetRecommendedChatFolders.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetRecommendedChatFolders.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return GetRecommendedChatFolders.CONSTRUCTOR;
		}
	}

	/**
	 * Returns a 2-step verification recovery email address that was
	 * previously set up. This method can be used to verify a password
	 * provided by the user.
	 * <p> Returns {@link RecoveryEmailAddress RecoveryEmailAddress} </p>
	**/
	public static final class GetRecoveryEmailAddress extends Function<RecoveryEmailAddress> {


		/**
		 * The 2-step verification password for the current user.
		**/
		public String password;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1594770947;

		/**
		 * Returns a 2-step verification recovery email address that was previously set up. This method can be used to verify a password provided by the user.
		 *
		 * <p> Returns {@link RecoveryEmailAddress RecoveryEmailAddress} </p>
		**/
		public GetRecoveryEmailAddress() {}

		/**
		 * Returns a 2-step verification recovery email address that was previously set up. This method can be used to verify a password provided by the user.
		 *
		 * <p> Returns {@link RecoveryEmailAddress RecoveryEmailAddress} </p>
		 *
		 * @param password The 2-step verification password for the current user.
		 *
		 * <p> Returns {@link RecoveryEmailAddress RecoveryEmailAddress} </p>
		**/
		public GetRecoveryEmailAddress(String password) {
			this.password = password;
		}

		/**
		 * Returns a 2-step verification recovery email address that was previously set up. This method can be used to verify a password provided by the user.
		 *
		 * <p> Returns {@link RecoveryEmailAddress RecoveryEmailAddress} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetRecoveryEmailAddress(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] passwordTmp = new byte[input.readInt()];
				input.readFully(passwordTmp);
				this.password = new String(passwordTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetRecoveryEmailAddress.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetRecoveryEmailAddress.CONSTRUCTOR);
			if (this.password == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] passwordTmp = this.password.getBytes(StandardCharsets.UTF_8);
				output.writeInt(passwordTmp.length);
				output.write(passwordTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetRecoveryEmailAddress getRecoveryEmailAddress = (GetRecoveryEmailAddress) o;
			if (this.password != getRecoveryEmailAddress.password) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.password == null ? 0 : this.password.hashCode();
		}
	}

	/**
	 * Returns information about a file by its remote ID; this is an offline
	 * request. Can be used to register a URL as a file for further
	 * uploading, or sending as a message. Even the request succeeds, the
	 * file can be used only if it is still accessible to the user. For
	 * example, if the file is from a message, then the message must be not
	 * deleted and accessible to the user. If the file database is disabled,
	 * then the corresponding object with the file must be preloaded by the
	 * application.
	 * <p> Returns {@link File File} </p>
	**/
	public static final class GetRemoteFile extends Function<File> {


		/**
		 * Remote identifier of the file to get.
		**/
		public String remoteFileId;

		/**
		 * File type; pass null if unknown.
		**/
		public FileType fileType;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2137204530;

		/**
		 * Returns information about a file by its remote ID; this is an offline request. Can be used to register a URL as a file for further uploading, or sending as a message. Even the request succeeds, the file can be used only if it is still accessible to the user. For example, if the file is from a message, then the message must be not deleted and accessible to the user. If the file database is disabled, then the corresponding object with the file must be preloaded by the application.
		 *
		 * <p> Returns {@link File File} </p>
		**/
		public GetRemoteFile() {}

		/**
		 * Returns information about a file by its remote ID; this is an offline request. Can be used to register a URL as a file for further uploading, or sending as a message. Even the request succeeds, the file can be used only if it is still accessible to the user. For example, if the file is from a message, then the message must be not deleted and accessible to the user. If the file database is disabled, then the corresponding object with the file must be preloaded by the application.
		 *
		 * <p> Returns {@link File File} </p>
		 *
		 * @param remoteFileId Remote identifier of the file to get.
		 * @param fileType File type; pass null if unknown.
		 *
		 * <p> Returns {@link File File} </p>
		**/
		public GetRemoteFile(String remoteFileId, FileType fileType) {
			this.remoteFileId = remoteFileId;
			this.fileType = fileType;
		}

		/**
		 * Returns information about a file by its remote ID; this is an offline request. Can be used to register a URL as a file for further uploading, or sending as a message. Even the request succeeds, the file can be used only if it is still accessible to the user. For example, if the file is from a message, then the message must be not deleted and accessible to the user. If the file database is disabled, then the corresponding object with the file must be preloaded by the application.
		 *
		 * <p> Returns {@link File File} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetRemoteFile(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] remoteFileIdTmp = new byte[input.readInt()];
				input.readFully(remoteFileIdTmp);
				this.remoteFileId = new String(remoteFileIdTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case FileTypeNone.CONSTRUCTOR: this.fileType = new FileTypeNone(input); break;
					case FileTypeAnimation.CONSTRUCTOR: this.fileType = new FileTypeAnimation(input); break;
					case FileTypeAudio.CONSTRUCTOR: this.fileType = new FileTypeAudio(input); break;
					case FileTypeDocument.CONSTRUCTOR: this.fileType = new FileTypeDocument(input); break;
					case FileTypeNotificationSound.CONSTRUCTOR: this.fileType = new FileTypeNotificationSound(input); break;
					case FileTypePhoto.CONSTRUCTOR: this.fileType = new FileTypePhoto(input); break;
					case FileTypeProfilePhoto.CONSTRUCTOR: this.fileType = new FileTypeProfilePhoto(input); break;
					case FileTypeSecret.CONSTRUCTOR: this.fileType = new FileTypeSecret(input); break;
					case FileTypeSecretThumbnail.CONSTRUCTOR: this.fileType = new FileTypeSecretThumbnail(input); break;
					case FileTypeSecure.CONSTRUCTOR: this.fileType = new FileTypeSecure(input); break;
					case FileTypeSticker.CONSTRUCTOR: this.fileType = new FileTypeSticker(input); break;
					case FileTypeThumbnail.CONSTRUCTOR: this.fileType = new FileTypeThumbnail(input); break;
					case FileTypeUnknown.CONSTRUCTOR: this.fileType = new FileTypeUnknown(input); break;
					case FileTypeVideo.CONSTRUCTOR: this.fileType = new FileTypeVideo(input); break;
					case FileTypeVideoNote.CONSTRUCTOR: this.fileType = new FileTypeVideoNote(input); break;
					case FileTypeVoiceNote.CONSTRUCTOR: this.fileType = new FileTypeVoiceNote(input); break;
					case FileTypeWallpaper.CONSTRUCTOR: this.fileType = new FileTypeWallpaper(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetRemoteFile.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetRemoteFile.CONSTRUCTOR);
			if (this.remoteFileId == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] remoteFileIdTmp = this.remoteFileId.getBytes(StandardCharsets.UTF_8);
				output.writeInt(remoteFileIdTmp.length);
				output.write(remoteFileIdTmp);
			}
			if (this.fileType == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.fileType.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetRemoteFile getRemoteFile = (GetRemoteFile) o;
			if (this.remoteFileId != getRemoteFile.remoteFileId) {
				return false;
			}
			if (!Objects.equals(this.fileType, getRemoteFile.fileType)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.remoteFileId == null ? 0 : this.remoteFileId.hashCode();
			result = result * 31 + (this.fileType == null ? 0 : this.fileType.hashCode());
			return result;
		}
	}

	/**
	 * Returns information about a message that is replied by a given
	 * message. Also, returns the pinned message, the game message, the
	 * invoice message, and the topic creation message for messages of the
	 * types messagePinMessage, messageGameScore, messagePaymentSuccessful,
	 * messageChatSetBackground and topic messages without replied message
	 * respectively.
	 * <p> Returns {@link Message Message} </p>
	**/
	public static final class GetRepliedMessage extends Function<Message> {


		/**
		 * Identifier of the chat the message belongs to.
		**/
		public long chatId;

		/**
		 * Identifier of the reply message.
		**/
		public long messageId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -641918531;

		/**
		 * Returns information about a message that is replied by a given message. Also, returns the pinned message, the game message, the invoice message, and the topic creation message for messages of the types messagePinMessage, messageGameScore, messagePaymentSuccessful, messageChatSetBackground and topic messages without replied message respectively.
		 *
		 * <p> Returns {@link Message Message} </p>
		**/
		public GetRepliedMessage() {}

		/**
		 * Returns information about a message that is replied by a given message. Also, returns the pinned message, the game message, the invoice message, and the topic creation message for messages of the types messagePinMessage, messageGameScore, messagePaymentSuccessful, messageChatSetBackground and topic messages without replied message respectively.
		 *
		 * <p> Returns {@link Message Message} </p>
		 *
		 * @param chatId Identifier of the chat the message belongs to.
		 * @param messageId Identifier of the reply message.
		 *
		 * <p> Returns {@link Message Message} </p>
		**/
		public GetRepliedMessage(long chatId, long messageId) {
			this.chatId = chatId;
			this.messageId = messageId;
		}

		/**
		 * Returns information about a message that is replied by a given message. Also, returns the pinned message, the game message, the invoice message, and the topic creation message for messages of the types messagePinMessage, messageGameScore, messagePaymentSuccessful, messageChatSetBackground and topic messages without replied message respectively.
		 *
		 * <p> Returns {@link Message Message} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetRepliedMessage(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetRepliedMessage.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetRepliedMessage.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetRepliedMessage getRepliedMessage = (GetRepliedMessage) o;
			if (this.chatId != getRepliedMessage.chatId) {
				return false;
			}
			if (this.messageId != getRepliedMessage.messageId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Returns saved animations.
	 * <p> Returns {@link Animations Animations} </p>
	**/
	public static final class GetSavedAnimations extends Function<Animations> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 7051032;

		/**
		 * Returns saved animations.
		 *
		 * <p> Returns {@link Animations Animations} </p>
		**/
		public GetSavedAnimations() {}

		/**
		 * Returns saved animations.
		 *
		 * <p> Returns {@link Animations Animations} </p>
		 *
		 *
		 * <p> Returns {@link Animations Animations} </p>
		**/

		/**
		 * Returns saved animations.
		 *
		 * <p> Returns {@link Animations Animations} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetSavedAnimations(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetSavedAnimations.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetSavedAnimations.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return GetSavedAnimations.CONSTRUCTOR;
		}
	}

	/**
	 * Returns saved notification sound by its identifier. Returns a 404
	 * error if there is no saved notification sound with the specified
	 * identifier.
	 * <p> Returns {@link NotificationSounds NotificationSounds} </p>
	**/
	public static final class GetSavedNotificationSound extends Function<NotificationSounds> {


		/**
		 * Identifier of the notification sound.
		**/
		public long notificationSoundId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 459569431;

		/**
		 * Returns saved notification sound by its identifier. Returns a 404 error if there is no saved notification sound with the specified identifier.
		 *
		 * <p> Returns {@link NotificationSounds NotificationSounds} </p>
		**/
		public GetSavedNotificationSound() {}

		/**
		 * Returns saved notification sound by its identifier. Returns a 404 error if there is no saved notification sound with the specified identifier.
		 *
		 * <p> Returns {@link NotificationSounds NotificationSounds} </p>
		 *
		 * @param notificationSoundId Identifier of the notification sound.
		 *
		 * <p> Returns {@link NotificationSounds NotificationSounds} </p>
		**/
		public GetSavedNotificationSound(long notificationSoundId) {
			this.notificationSoundId = notificationSoundId;
		}

		/**
		 * Returns saved notification sound by its identifier. Returns a 404 error if there is no saved notification sound with the specified identifier.
		 *
		 * <p> Returns {@link NotificationSounds NotificationSounds} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetSavedNotificationSound(DataInput input) throws IOException {
			this.notificationSoundId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetSavedNotificationSound.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetSavedNotificationSound.CONSTRUCTOR);
			output.writeLong(this.notificationSoundId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetSavedNotificationSound getSavedNotificationSound = (GetSavedNotificationSound) o;
			if (this.notificationSoundId != getSavedNotificationSound.notificationSoundId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.notificationSoundId);
		}
	}

	/**
	 * Returns list of saved notification sounds. If a sound isn&#039;t in
	 * the list, then default sound needs to be used.
	 * <p> Returns {@link NotificationSounds NotificationSounds} </p>
	**/
	public static final class GetSavedNotificationSounds extends Function<NotificationSounds> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1070305368;

		/**
		 * Returns list of saved notification sounds. If a sound isn&#039;t in the list, then default sound needs to be used.
		 *
		 * <p> Returns {@link NotificationSounds NotificationSounds} </p>
		**/
		public GetSavedNotificationSounds() {}

		/**
		 * Returns list of saved notification sounds. If a sound isn&#039;t in the list, then default sound needs to be used.
		 *
		 * <p> Returns {@link NotificationSounds NotificationSounds} </p>
		 *
		 *
		 * <p> Returns {@link NotificationSounds NotificationSounds} </p>
		**/

		/**
		 * Returns list of saved notification sounds. If a sound isn&#039;t in the list, then default sound needs to be used.
		 *
		 * <p> Returns {@link NotificationSounds NotificationSounds} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetSavedNotificationSounds(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetSavedNotificationSounds.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetSavedNotificationSounds.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return GetSavedNotificationSounds.CONSTRUCTOR;
		}
	}

	/**
	 * Returns saved order information. Returns a 404 error if there is no
	 * saved order information.
	 * <p> Returns {@link OrderInfo OrderInfo} </p>
	**/
	public static final class GetSavedOrderInfo extends Function<OrderInfo> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1152016675;

		/**
		 * Returns saved order information. Returns a 404 error if there is no saved order information.
		 *
		 * <p> Returns {@link OrderInfo OrderInfo} </p>
		**/
		public GetSavedOrderInfo() {}

		/**
		 * Returns saved order information. Returns a 404 error if there is no saved order information.
		 *
		 * <p> Returns {@link OrderInfo OrderInfo} </p>
		 *
		 *
		 * <p> Returns {@link OrderInfo OrderInfo} </p>
		**/

		/**
		 * Returns saved order information. Returns a 404 error if there is no saved order information.
		 *
		 * <p> Returns {@link OrderInfo OrderInfo} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetSavedOrderInfo(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetSavedOrderInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetSavedOrderInfo.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return GetSavedOrderInfo.CONSTRUCTOR;
		}
	}

	/**
	 * Returns the notification settings for chats of a given type.
	 * <p> Returns {@link ScopeNotificationSettings
	 * ScopeNotificationSettings} </p>
	**/
	public static final class GetScopeNotificationSettings extends Function<ScopeNotificationSettings> {


		/**
		 * Types of chats for which to return the notification settings information.
		**/
		public NotificationSettingsScope scope;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -995613361;

		/**
		 * Returns the notification settings for chats of a given type.
		 *
		 * <p> Returns {@link ScopeNotificationSettings ScopeNotificationSettings} </p>
		**/
		public GetScopeNotificationSettings() {}

		/**
		 * Returns the notification settings for chats of a given type.
		 *
		 * <p> Returns {@link ScopeNotificationSettings ScopeNotificationSettings} </p>
		 *
		 * @param scope Types of chats for which to return the notification settings information.
		 *
		 * <p> Returns {@link ScopeNotificationSettings ScopeNotificationSettings} </p>
		**/
		public GetScopeNotificationSettings(NotificationSettingsScope scope) {
			this.scope = scope;
		}

		/**
		 * Returns the notification settings for chats of a given type.
		 *
		 * <p> Returns {@link ScopeNotificationSettings ScopeNotificationSettings} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetScopeNotificationSettings(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case NotificationSettingsScopePrivateChats.CONSTRUCTOR: this.scope = new NotificationSettingsScopePrivateChats(input); break;
					case NotificationSettingsScopeGroupChats.CONSTRUCTOR: this.scope = new NotificationSettingsScopeGroupChats(input); break;
					case NotificationSettingsScopeChannelChats.CONSTRUCTOR: this.scope = new NotificationSettingsScopeChannelChats(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetScopeNotificationSettings.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetScopeNotificationSettings.CONSTRUCTOR);
			if (this.scope == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.scope.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetScopeNotificationSettings getScopeNotificationSettings = (GetScopeNotificationSettings) o;
			if (!Objects.equals(this.scope, getScopeNotificationSettings.scope)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.scope == null ? 0 : this.scope.hashCode();
		}
	}

	/**
	 * Returns information about a secret chat by its identifier. This is an
	 * offline request.
	 * <p> Returns {@link SecretChat SecretChat} </p>
	**/
	public static final class GetSecretChat extends Function<SecretChat> {


		/**
		 * Secret chat identifier.
		**/
		public int secretChatId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 40599169;

		/**
		 * Returns information about a secret chat by its identifier. This is an offline request.
		 *
		 * <p> Returns {@link SecretChat SecretChat} </p>
		**/
		public GetSecretChat() {}

		/**
		 * Returns information about a secret chat by its identifier. This is an offline request.
		 *
		 * <p> Returns {@link SecretChat SecretChat} </p>
		 *
		 * @param secretChatId Secret chat identifier.
		 *
		 * <p> Returns {@link SecretChat SecretChat} </p>
		**/
		public GetSecretChat(int secretChatId) {
			this.secretChatId = secretChatId;
		}

		/**
		 * Returns information about a secret chat by its identifier. This is an offline request.
		 *
		 * <p> Returns {@link SecretChat SecretChat} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetSecretChat(DataInput input) throws IOException {
			this.secretChatId = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetSecretChat.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetSecretChat.CONSTRUCTOR);
			output.writeInt(this.secretChatId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetSecretChat getSecretChat = (GetSecretChat) o;
			if (this.secretChatId != getSecretChat.secretChatId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.secretChatId);
		}
	}

	/**
	 * Loads an asynchronous or a zoomed in statistical graph.
	 * <p> Returns {@link StatisticalGraph StatisticalGraph} </p>
	**/
	public static final class GetStatisticalGraph extends Function<StatisticalGraph> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * The token for graph loading.
		**/
		public String token;

		/**
		 * X-value for zoomed in graph or 0 otherwise.
		**/
		public long x;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1100975515;

		/**
		 * Loads an asynchronous or a zoomed in statistical graph.
		 *
		 * <p> Returns {@link StatisticalGraph StatisticalGraph} </p>
		**/
		public GetStatisticalGraph() {}

		/**
		 * Loads an asynchronous or a zoomed in statistical graph.
		 *
		 * <p> Returns {@link StatisticalGraph StatisticalGraph} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param token The token for graph loading.
		 * @param x X-value for zoomed in graph or 0 otherwise.
		 *
		 * <p> Returns {@link StatisticalGraph StatisticalGraph} </p>
		**/
		public GetStatisticalGraph(long chatId, String token, long x) {
			this.chatId = chatId;
			this.token = token;
			this.x = x;
		}

		/**
		 * Loads an asynchronous or a zoomed in statistical graph.
		 *
		 * <p> Returns {@link StatisticalGraph StatisticalGraph} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetStatisticalGraph(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				byte[] tokenTmp = new byte[input.readInt()];
				input.readFully(tokenTmp);
				this.token = new String(tokenTmp, StandardCharsets.UTF_8);
			}
			this.x = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetStatisticalGraph.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetStatisticalGraph.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.token == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] tokenTmp = this.token.getBytes(StandardCharsets.UTF_8);
				output.writeInt(tokenTmp.length);
				output.write(tokenTmp);
			}
			output.writeLong(this.x);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetStatisticalGraph getStatisticalGraph = (GetStatisticalGraph) o;
			if (this.chatId != getStatisticalGraph.chatId) {
				return false;
			}
			if (this.token != getStatisticalGraph.token) {
				return false;
			}
			if (this.x != getStatisticalGraph.x) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.token == null ? 0 : this.token.hashCode());
			return result;
		}
	}

	/**
	 * Returns emoji corresponding to a sticker. The list is only for
	 * informational purposes, because a sticker is always sent with a fixed
	 * emoji from the corresponding Sticker object.
	 * <p> Returns {@link Emojis Emojis} </p>
	**/
	public static final class GetStickerEmojis extends Function<Emojis> {


		/**
		 * Sticker file identifier.
		**/
		public InputFile sticker;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1895508665;

		/**
		 * Returns emoji corresponding to a sticker. The list is only for informational purposes, because a sticker is always sent with a fixed emoji from the corresponding Sticker object.
		 *
		 * <p> Returns {@link Emojis Emojis} </p>
		**/
		public GetStickerEmojis() {}

		/**
		 * Returns emoji corresponding to a sticker. The list is only for informational purposes, because a sticker is always sent with a fixed emoji from the corresponding Sticker object.
		 *
		 * <p> Returns {@link Emojis Emojis} </p>
		 *
		 * @param sticker Sticker file identifier.
		 *
		 * <p> Returns {@link Emojis Emojis} </p>
		**/
		public GetStickerEmojis(InputFile sticker) {
			this.sticker = sticker;
		}

		/**
		 * Returns emoji corresponding to a sticker. The list is only for informational purposes, because a sticker is always sent with a fixed emoji from the corresponding Sticker object.
		 *
		 * <p> Returns {@link Emojis Emojis} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetStickerEmojis(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputFileId.CONSTRUCTOR: this.sticker = new InputFileId(input); break;
					case InputFileRemote.CONSTRUCTOR: this.sticker = new InputFileRemote(input); break;
					case InputFileLocal.CONSTRUCTOR: this.sticker = new InputFileLocal(input); break;
					case InputFileGenerated.CONSTRUCTOR: this.sticker = new InputFileGenerated(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetStickerEmojis.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetStickerEmojis.CONSTRUCTOR);
			if (this.sticker == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.sticker.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetStickerEmojis getStickerEmojis = (GetStickerEmojis) o;
			if (!Objects.equals(this.sticker, getStickerEmojis.sticker)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.sticker == null ? 0 : this.sticker.hashCode();
		}
	}

	/**
	 * Returns information about a sticker set by its identifier.
	 * <p> Returns {@link StickerSet StickerSet} </p>
	**/
	public static final class GetStickerSet extends Function<StickerSet> {


		/**
		 * Identifier of the sticker set.
		**/
		public long setId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1052318659;

		/**
		 * Returns information about a sticker set by its identifier.
		 *
		 * <p> Returns {@link StickerSet StickerSet} </p>
		**/
		public GetStickerSet() {}

		/**
		 * Returns information about a sticker set by its identifier.
		 *
		 * <p> Returns {@link StickerSet StickerSet} </p>
		 *
		 * @param setId Identifier of the sticker set.
		 *
		 * <p> Returns {@link StickerSet StickerSet} </p>
		**/
		public GetStickerSet(long setId) {
			this.setId = setId;
		}

		/**
		 * Returns information about a sticker set by its identifier.
		 *
		 * <p> Returns {@link StickerSet StickerSet} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetStickerSet(DataInput input) throws IOException {
			this.setId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetStickerSet.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetStickerSet.CONSTRUCTOR);
			output.writeLong(this.setId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetStickerSet getStickerSet = (GetStickerSet) o;
			if (this.setId != getStickerSet.setId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.setId);
		}
	}

	/**
	 * Returns stickers from the installed sticker sets that correspond to
	 * any of the given emoji or can be found by sticker-specific keywords.
	 * If the query is non-empty, then favorite, recently used or trending
	 * stickers may also be returned.
	 * <p> Returns {@link Stickers Stickers} </p>
	**/
	public static final class GetStickers extends Function<Stickers> {


		/**
		 * Type of the stickers to return.
		**/
		public StickerType stickerType;

		/**
		 * Search query; a space-separated list of emoji or a keyword prefix. If empty, returns all known installed stickers.
		**/
		public String query;

		/**
		 * The maximum number of stickers to be returned.
		**/
		public int limit;

		/**
		 * Chat identifier for which to return stickers. Available custom emoji stickers may be different for different chats.
		**/
		public long chatId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1158058819;

		/**
		 * Returns stickers from the installed sticker sets that correspond to any of the given emoji or can be found by sticker-specific keywords. If the query is non-empty, then favorite, recently used or trending stickers may also be returned.
		 *
		 * <p> Returns {@link Stickers Stickers} </p>
		**/
		public GetStickers() {}

		/**
		 * Returns stickers from the installed sticker sets that correspond to any of the given emoji or can be found by sticker-specific keywords. If the query is non-empty, then favorite, recently used or trending stickers may also be returned.
		 *
		 * <p> Returns {@link Stickers Stickers} </p>
		 *
		 * @param stickerType Type of the stickers to return.
		 * @param query Search query; a space-separated list of emoji or a keyword prefix. If empty, returns all known installed stickers.
		 * @param limit The maximum number of stickers to be returned.
		 * @param chatId Chat identifier for which to return stickers. Available custom emoji stickers may be different for different chats.
		 *
		 * <p> Returns {@link Stickers Stickers} </p>
		**/
		public GetStickers(StickerType stickerType,
				String query,
				int limit,
				long chatId) {
			this.stickerType = stickerType;
			this.query = query;
			this.limit = limit;
			this.chatId = chatId;
		}

		/**
		 * Returns stickers from the installed sticker sets that correspond to any of the given emoji or can be found by sticker-specific keywords. If the query is non-empty, then favorite, recently used or trending stickers may also be returned.
		 *
		 * <p> Returns {@link Stickers Stickers} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetStickers(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case StickerTypeRegular.CONSTRUCTOR: this.stickerType = new StickerTypeRegular(input); break;
					case StickerTypeMask.CONSTRUCTOR: this.stickerType = new StickerTypeMask(input); break;
					case StickerTypeCustomEmoji.CONSTRUCTOR: this.stickerType = new StickerTypeCustomEmoji(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				byte[] queryTmp = new byte[input.readInt()];
				input.readFully(queryTmp);
				this.query = new String(queryTmp, StandardCharsets.UTF_8);
			}
			this.limit = input.readInt();
			this.chatId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetStickers.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetStickers.CONSTRUCTOR);
			if (this.stickerType == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.stickerType.serialize(output);
			}
			if (this.query == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] queryTmp = this.query.getBytes(StandardCharsets.UTF_8);
				output.writeInt(queryTmp.length);
				output.write(queryTmp);
			}
			output.writeInt(this.limit);
			output.writeLong(this.chatId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetStickers getStickers = (GetStickers) o;
			if (!Objects.equals(this.stickerType, getStickers.stickerType)) {
				return false;
			}
			if (this.query != getStickers.query) {
				return false;
			}
			if (this.limit != getStickers.limit) {
				return false;
			}
			if (this.chatId != getStickers.chatId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.limit);
			result = result * 31 + (this.stickerType == null ? 0 : this.stickerType.hashCode());
			result = result * 31 + (this.query == null ? 0 : this.query.hashCode());
			return result;
		}
	}

	/**
	 * Returns storage usage statistics. Can be called before authorization.
	 * <p> Returns {@link StorageStatistics StorageStatistics} </p>
	**/
	public static final class GetStorageStatistics extends Function<StorageStatistics> {


		/**
		 * The maximum number of chats with the largest storage usage for which separate statistics need to be returned. All other chats will be grouped in entries with chatId == 0. If the chat info database is not used, the chatLimit is ignored and is always set to 0.
		**/
		public int chatLimit;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -853193929;

		/**
		 * Returns storage usage statistics. Can be called before authorization.
		 *
		 * <p> Returns {@link StorageStatistics StorageStatistics} </p>
		**/
		public GetStorageStatistics() {}

		/**
		 * Returns storage usage statistics. Can be called before authorization.
		 *
		 * <p> Returns {@link StorageStatistics StorageStatistics} </p>
		 *
		 * @param chatLimit The maximum number of chats with the largest storage usage for which separate statistics need to be returned. All other chats will be grouped in entries with chatId == 0. If the chat info database is not used, the chatLimit is ignored and is always set to 0.
		 *
		 * <p> Returns {@link StorageStatistics StorageStatistics} </p>
		**/
		public GetStorageStatistics(int chatLimit) {
			this.chatLimit = chatLimit;
		}

		/**
		 * Returns storage usage statistics. Can be called before authorization.
		 *
		 * <p> Returns {@link StorageStatistics StorageStatistics} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetStorageStatistics(DataInput input) throws IOException {
			this.chatLimit = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetStorageStatistics.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetStorageStatistics.CONSTRUCTOR);
			output.writeInt(this.chatLimit);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetStorageStatistics getStorageStatistics = (GetStorageStatistics) o;
			if (this.chatLimit != getStorageStatistics.chatLimit) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.chatLimit);
		}
	}

	/**
	 * Quickly returns approximate storage usage statistics. Can be called
	 * before authorization.
	 * <p> Returns {@link StorageStatisticsFast StorageStatisticsFast} </p>
	**/
	public static final class GetStorageStatisticsFast extends Function<StorageStatisticsFast> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 61368066;

		/**
		 * Quickly returns approximate storage usage statistics. Can be called before authorization.
		 *
		 * <p> Returns {@link StorageStatisticsFast StorageStatisticsFast} </p>
		**/
		public GetStorageStatisticsFast() {}

		/**
		 * Quickly returns approximate storage usage statistics. Can be called before authorization.
		 *
		 * <p> Returns {@link StorageStatisticsFast StorageStatisticsFast} </p>
		 *
		 *
		 * <p> Returns {@link StorageStatisticsFast StorageStatisticsFast} </p>
		**/

		/**
		 * Quickly returns approximate storage usage statistics. Can be called before authorization.
		 *
		 * <p> Returns {@link StorageStatisticsFast StorageStatisticsFast} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetStorageStatisticsFast(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetStorageStatisticsFast.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetStorageStatisticsFast.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return GetStorageStatisticsFast.CONSTRUCTOR;
		}
	}

	/**
	 * Returns suggested name for saving a file in a given directory.
	 * <p> Returns {@link Text Text} </p>
	**/
	public static final class GetSuggestedFileName extends Function<Text> {


		/**
		 * Identifier of the file.
		**/
		public int fileId;

		/**
		 * Directory in which the file is supposed to be saved.
		**/
		public String directory;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2049399674;

		/**
		 * Returns suggested name for saving a file in a given directory.
		 *
		 * <p> Returns {@link Text Text} </p>
		**/
		public GetSuggestedFileName() {}

		/**
		 * Returns suggested name for saving a file in a given directory.
		 *
		 * <p> Returns {@link Text Text} </p>
		 *
		 * @param fileId Identifier of the file.
		 * @param directory Directory in which the file is supposed to be saved.
		 *
		 * <p> Returns {@link Text Text} </p>
		**/
		public GetSuggestedFileName(int fileId, String directory) {
			this.fileId = fileId;
			this.directory = directory;
		}

		/**
		 * Returns suggested name for saving a file in a given directory.
		 *
		 * <p> Returns {@link Text Text} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetSuggestedFileName(DataInput input) throws IOException {
			this.fileId = input.readInt();
			if (input.readBoolean()) {
				byte[] directoryTmp = new byte[input.readInt()];
				input.readFully(directoryTmp);
				this.directory = new String(directoryTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetSuggestedFileName.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetSuggestedFileName.CONSTRUCTOR);
			output.writeInt(this.fileId);
			if (this.directory == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] directoryTmp = this.directory.getBytes(StandardCharsets.UTF_8);
				output.writeInt(directoryTmp.length);
				output.write(directoryTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetSuggestedFileName getSuggestedFileName = (GetSuggestedFileName) o;
			if (this.fileId != getSuggestedFileName.fileId) {
				return false;
			}
			if (this.directory != getSuggestedFileName.directory) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.fileId);
			result = result * 31 + (this.directory == null ? 0 : this.directory.hashCode());
			return result;
		}
	}

	/**
	 * Returns a suggested name for a new sticker set with a given title.
	 * <p> Returns {@link Text Text} </p>
	**/
	public static final class GetSuggestedStickerSetName extends Function<Text> {


		/**
		 * Sticker set title; 1-64 characters.
		**/
		public String title;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1340995520;

		/**
		 * Returns a suggested name for a new sticker set with a given title.
		 *
		 * <p> Returns {@link Text Text} </p>
		**/
		public GetSuggestedStickerSetName() {}

		/**
		 * Returns a suggested name for a new sticker set with a given title.
		 *
		 * <p> Returns {@link Text Text} </p>
		 *
		 * @param title Sticker set title; 1-64 characters.
		 *
		 * <p> Returns {@link Text Text} </p>
		**/
		public GetSuggestedStickerSetName(String title) {
			this.title = title;
		}

		/**
		 * Returns a suggested name for a new sticker set with a given title.
		 *
		 * <p> Returns {@link Text Text} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetSuggestedStickerSetName(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetSuggestedStickerSetName.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetSuggestedStickerSetName.CONSTRUCTOR);
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetSuggestedStickerSetName getSuggestedStickerSetName = (GetSuggestedStickerSetName) o;
			if (this.title != getSuggestedStickerSetName.title) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.title == null ? 0 : this.title.hashCode();
		}
	}

	/**
	 * Returns a list of basic group and supergroup chats, which can be used
	 * as a discussion group for a channel. Returned basic group chats must
	 * be first upgraded to supergroups before they can be set as a
	 * discussion group. To set a returned supergroup as a discussion group,
	 * access to its old messages must be enabled using
	 * toggleSupergroupIsAllHistoryAvailable first.
	 * <p> Returns {@link Chats Chats} </p>
	**/
	public static final class GetSuitableDiscussionChats extends Function<Chats> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 49044982;

		/**
		 * Returns a list of basic group and supergroup chats, which can be used as a discussion group for a channel. Returned basic group chats must be first upgraded to supergroups before they can be set as a discussion group. To set a returned supergroup as a discussion group, access to its old messages must be enabled using toggleSupergroupIsAllHistoryAvailable first.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		**/
		public GetSuitableDiscussionChats() {}

		/**
		 * Returns a list of basic group and supergroup chats, which can be used as a discussion group for a channel. Returned basic group chats must be first upgraded to supergroups before they can be set as a discussion group. To set a returned supergroup as a discussion group, access to its old messages must be enabled using toggleSupergroupIsAllHistoryAvailable first.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		 *
		 *
		 * <p> Returns {@link Chats Chats} </p>
		**/

		/**
		 * Returns a list of basic group and supergroup chats, which can be used as a discussion group for a channel. Returned basic group chats must be first upgraded to supergroups before they can be set as a discussion group. To set a returned supergroup as a discussion group, access to its old messages must be enabled using toggleSupergroupIsAllHistoryAvailable first.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetSuitableDiscussionChats(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetSuitableDiscussionChats.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetSuitableDiscussionChats.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return GetSuitableDiscussionChats.CONSTRUCTOR;
		}
	}

	/**
	 * Returns information about a supergroup or a channel by its
	 * identifier. This is an offline request if the current user is not a
	 * bot.
	 * <p> Returns {@link Supergroup Supergroup} </p>
	**/
	public static final class GetSupergroup extends Function<Supergroup> {


		/**
		 * Supergroup or channel identifier.
		**/
		public long supergroupId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 989663458;

		/**
		 * Returns information about a supergroup or a channel by its identifier. This is an offline request if the current user is not a bot.
		 *
		 * <p> Returns {@link Supergroup Supergroup} </p>
		**/
		public GetSupergroup() {}

		/**
		 * Returns information about a supergroup or a channel by its identifier. This is an offline request if the current user is not a bot.
		 *
		 * <p> Returns {@link Supergroup Supergroup} </p>
		 *
		 * @param supergroupId Supergroup or channel identifier.
		 *
		 * <p> Returns {@link Supergroup Supergroup} </p>
		**/
		public GetSupergroup(long supergroupId) {
			this.supergroupId = supergroupId;
		}

		/**
		 * Returns information about a supergroup or a channel by its identifier. This is an offline request if the current user is not a bot.
		 *
		 * <p> Returns {@link Supergroup Supergroup} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetSupergroup(DataInput input) throws IOException {
			this.supergroupId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetSupergroup.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetSupergroup.CONSTRUCTOR);
			output.writeLong(this.supergroupId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetSupergroup getSupergroup = (GetSupergroup) o;
			if (this.supergroupId != getSupergroup.supergroupId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.supergroupId);
		}
	}

	/**
	 * Returns full information about a supergroup or a channel by its
	 * identifier, cached for up to 1 minute.
	 * <p> Returns {@link SupergroupFullInfo SupergroupFullInfo} </p>
	**/
	public static final class GetSupergroupFullInfo extends Function<SupergroupFullInfo> {


		/**
		 * Supergroup or channel identifier.
		**/
		public long supergroupId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1099776056;

		/**
		 * Returns full information about a supergroup or a channel by its identifier, cached for up to 1 minute.
		 *
		 * <p> Returns {@link SupergroupFullInfo SupergroupFullInfo} </p>
		**/
		public GetSupergroupFullInfo() {}

		/**
		 * Returns full information about a supergroup or a channel by its identifier, cached for up to 1 minute.
		 *
		 * <p> Returns {@link SupergroupFullInfo SupergroupFullInfo} </p>
		 *
		 * @param supergroupId Supergroup or channel identifier.
		 *
		 * <p> Returns {@link SupergroupFullInfo SupergroupFullInfo} </p>
		**/
		public GetSupergroupFullInfo(long supergroupId) {
			this.supergroupId = supergroupId;
		}

		/**
		 * Returns full information about a supergroup or a channel by its identifier, cached for up to 1 minute.
		 *
		 * <p> Returns {@link SupergroupFullInfo SupergroupFullInfo} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetSupergroupFullInfo(DataInput input) throws IOException {
			this.supergroupId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetSupergroupFullInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetSupergroupFullInfo.CONSTRUCTOR);
			output.writeLong(this.supergroupId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetSupergroupFullInfo getSupergroupFullInfo = (GetSupergroupFullInfo) o;
			if (this.supergroupId != getSupergroupFullInfo.supergroupId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.supergroupId);
		}
	}

	/**
	 * Returns information about members or banned users in a supergroup or
	 * channel. Can be used only if supergroupFullInfo.canGetMembers ==
	 * true; additionally, administrator privileges may be required for some
	 * filters.
	 * <p> Returns {@link ChatMembers ChatMembers} </p>
	**/
	public static final class GetSupergroupMembers extends Function<ChatMembers> {


		/**
		 * Identifier of the supergroup or channel.
		**/
		public long supergroupId;

		/**
		 * The type of users to return; pass null to use supergroupMembersFilterRecent.
		**/
		public SupergroupMembersFilter filter;

		/**
		 * Number of users to skip.
		**/
		public int offset;

		/**
		 * The maximum number of users be returned; up to 200.
		**/
		public int limit;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -570940984;

		/**
		 * Returns information about members or banned users in a supergroup or channel. Can be used only if supergroupFullInfo.canGetMembers == true; additionally, administrator privileges may be required for some filters.
		 *
		 * <p> Returns {@link ChatMembers ChatMembers} </p>
		**/
		public GetSupergroupMembers() {}

		/**
		 * Returns information about members or banned users in a supergroup or channel. Can be used only if supergroupFullInfo.canGetMembers == true; additionally, administrator privileges may be required for some filters.
		 *
		 * <p> Returns {@link ChatMembers ChatMembers} </p>
		 *
		 * @param supergroupId Identifier of the supergroup or channel.
		 * @param filter The type of users to return; pass null to use supergroupMembersFilterRecent.
		 * @param offset Number of users to skip.
		 * @param limit The maximum number of users be returned; up to 200.
		 *
		 * <p> Returns {@link ChatMembers ChatMembers} </p>
		**/
		public GetSupergroupMembers(long supergroupId,
				SupergroupMembersFilter filter,
				int offset,
				int limit) {
			this.supergroupId = supergroupId;
			this.filter = filter;
			this.offset = offset;
			this.limit = limit;
		}

		/**
		 * Returns information about members or banned users in a supergroup or channel. Can be used only if supergroupFullInfo.canGetMembers == true; additionally, administrator privileges may be required for some filters.
		 *
		 * <p> Returns {@link ChatMembers ChatMembers} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetSupergroupMembers(DataInput input) throws IOException {
			this.supergroupId = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case SupergroupMembersFilterRecent.CONSTRUCTOR: this.filter = new SupergroupMembersFilterRecent(input); break;
					case SupergroupMembersFilterContacts.CONSTRUCTOR: this.filter = new SupergroupMembersFilterContacts(input); break;
					case SupergroupMembersFilterAdministrators.CONSTRUCTOR: this.filter = new SupergroupMembersFilterAdministrators(input); break;
					case SupergroupMembersFilterSearch.CONSTRUCTOR: this.filter = new SupergroupMembersFilterSearch(input); break;
					case SupergroupMembersFilterRestricted.CONSTRUCTOR: this.filter = new SupergroupMembersFilterRestricted(input); break;
					case SupergroupMembersFilterBanned.CONSTRUCTOR: this.filter = new SupergroupMembersFilterBanned(input); break;
					case SupergroupMembersFilterMention.CONSTRUCTOR: this.filter = new SupergroupMembersFilterMention(input); break;
					case SupergroupMembersFilterBots.CONSTRUCTOR: this.filter = new SupergroupMembersFilterBots(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.offset = input.readInt();
			this.limit = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetSupergroupMembers.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetSupergroupMembers.CONSTRUCTOR);
			output.writeLong(this.supergroupId);
			if (this.filter == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.filter.serialize(output);
			}
			output.writeInt(this.offset);
			output.writeInt(this.limit);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetSupergroupMembers getSupergroupMembers = (GetSupergroupMembers) o;
			if (this.supergroupId != getSupergroupMembers.supergroupId) {
				return false;
			}
			if (!Objects.equals(this.filter, getSupergroupMembers.filter)) {
				return false;
			}
			if (this.offset != getSupergroupMembers.offset) {
				return false;
			}
			if (this.limit != getSupergroupMembers.limit) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.supergroupId);
			result = result * 31 + (this.filter == null ? 0 : this.filter.hashCode());
			return result;
		}
	}

	/**
	 * Returns localized name of the Telegram support user; for Telegram
	 * support only.
	 * <p> Returns {@link Text Text} </p>
	**/
	public static final class GetSupportName extends Function<Text> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1302205794;

		/**
		 * Returns localized name of the Telegram support user; for Telegram support only.
		 *
		 * <p> Returns {@link Text Text} </p>
		**/
		public GetSupportName() {}

		/**
		 * Returns localized name of the Telegram support user; for Telegram support only.
		 *
		 * <p> Returns {@link Text Text} </p>
		 *
		 *
		 * <p> Returns {@link Text Text} </p>
		**/

		/**
		 * Returns localized name of the Telegram support user; for Telegram support only.
		 *
		 * <p> Returns {@link Text Text} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetSupportName(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetSupportName.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetSupportName.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return GetSupportName.CONSTRUCTOR;
		}
	}

	/**
	 * Returns a user that can be contacted to get support.
	 * <p> Returns {@link User User} </p>
	**/
	public static final class GetSupportUser extends Function<User> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1733497700;

		/**
		 * Returns a user that can be contacted to get support.
		 *
		 * <p> Returns {@link User User} </p>
		**/
		public GetSupportUser() {}

		/**
		 * Returns a user that can be contacted to get support.
		 *
		 * <p> Returns {@link User User} </p>
		 *
		 *
		 * <p> Returns {@link User User} </p>
		**/

		/**
		 * Returns a user that can be contacted to get support.
		 *
		 * <p> Returns {@link User User} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetSupportUser(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetSupportUser.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetSupportUser.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return GetSupportUser.CONSTRUCTOR;
		}
	}

	/**
	 * Returns information about the current temporary password.
	 * <p> Returns {@link TemporaryPasswordState TemporaryPasswordState} </p>
	**/
	public static final class GetTemporaryPasswordState extends Function<TemporaryPasswordState> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -12670830;

		/**
		 * Returns information about the current temporary password.
		 *
		 * <p> Returns {@link TemporaryPasswordState TemporaryPasswordState} </p>
		**/
		public GetTemporaryPasswordState() {}

		/**
		 * Returns information about the current temporary password.
		 *
		 * <p> Returns {@link TemporaryPasswordState TemporaryPasswordState} </p>
		 *
		 *
		 * <p> Returns {@link TemporaryPasswordState TemporaryPasswordState} </p>
		**/

		/**
		 * Returns information about the current temporary password.
		 *
		 * <p> Returns {@link TemporaryPasswordState TemporaryPasswordState} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetTemporaryPasswordState(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetTemporaryPasswordState.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetTemporaryPasswordState.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return GetTemporaryPasswordState.CONSTRUCTOR;
		}
	}

	/**
	 * Returns all entities (mentions, hashtags, cashtags, bot commands,
	 * bank card numbers, URLs, and email addresses) found in the text. Can
	 * be called synchronously.
	 * <p> Returns {@link TextEntities TextEntities} </p>
	**/
	public static final class GetTextEntities extends Function<TextEntities> {


		/**
		 * The text in which to look for entities.
		**/
		public String text;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -341490693;

		/**
		 * Returns all entities (mentions, hashtags, cashtags, bot commands, bank card numbers, URLs, and email addresses) found in the text. Can be called synchronously.
		 *
		 * <p> Returns {@link TextEntities TextEntities} </p>
		**/
		public GetTextEntities() {}

		/**
		 * Returns all entities (mentions, hashtags, cashtags, bot commands, bank card numbers, URLs, and email addresses) found in the text. Can be called synchronously.
		 *
		 * <p> Returns {@link TextEntities TextEntities} </p>
		 *
		 * @param text The text in which to look for entities.
		 *
		 * <p> Returns {@link TextEntities TextEntities} </p>
		**/
		public GetTextEntities(String text) {
			this.text = text;
		}

		/**
		 * Returns all entities (mentions, hashtags, cashtags, bot commands, bank card numbers, URLs, and email addresses) found in the text. Can be called synchronously.
		 *
		 * <p> Returns {@link TextEntities TextEntities} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetTextEntities(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] textTmp = new byte[input.readInt()];
				input.readFully(textTmp);
				this.text = new String(textTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetTextEntities.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetTextEntities.CONSTRUCTOR);
			if (this.text == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] textTmp = this.text.getBytes(StandardCharsets.UTF_8);
				output.writeInt(textTmp.length);
				output.write(textTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetTextEntities getTextEntities = (GetTextEntities) o;
			if (this.text != getTextEntities.text) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.text == null ? 0 : this.text.hashCode();
		}
	}

	/**
	 * Converts a themeParameters object to corresponding JSON-serialized
	 * string. Can be called synchronously.
	 * <p> Returns {@link Text Text} </p>
	**/
	public static final class GetThemeParametersJsonString extends Function<Text> {


		/**
		 * Theme parameters to convert to JSON.
		**/
		public ThemeParameters theme;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1850145288;

		/**
		 * Converts a themeParameters object to corresponding JSON-serialized string. Can be called synchronously.
		 *
		 * <p> Returns {@link Text Text} </p>
		**/
		public GetThemeParametersJsonString() {}

		/**
		 * Converts a themeParameters object to corresponding JSON-serialized string. Can be called synchronously.
		 *
		 * <p> Returns {@link Text Text} </p>
		 *
		 * @param theme Theme parameters to convert to JSON.
		 *
		 * <p> Returns {@link Text Text} </p>
		**/
		public GetThemeParametersJsonString(ThemeParameters theme) {
			this.theme = theme;
		}

		/**
		 * Converts a themeParameters object to corresponding JSON-serialized string. Can be called synchronously.
		 *
		 * <p> Returns {@link Text Text} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetThemeParametersJsonString(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (ThemeParameters.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.theme = new ThemeParameters(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetThemeParametersJsonString.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetThemeParametersJsonString.CONSTRUCTOR);
			if (this.theme == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.theme.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetThemeParametersJsonString getThemeParametersJsonString = (GetThemeParametersJsonString) o;
			if (!Objects.equals(this.theme, getThemeParametersJsonString.theme)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.theme == null ? 0 : this.theme.hashCode();
		}
	}

	/**
	 * Returns up to 8 emoji statuses, which must be shown right after the
	 * default Premium Badge in the emoji status list.
	 * <p> Returns {@link EmojiStatuses EmojiStatuses} </p>
	**/
	public static final class GetThemedEmojiStatuses extends Function<EmojiStatuses> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1791346882;

		/**
		 * Returns up to 8 emoji statuses, which must be shown right after the default Premium Badge in the emoji status list.
		 *
		 * <p> Returns {@link EmojiStatuses EmojiStatuses} </p>
		**/
		public GetThemedEmojiStatuses() {}

		/**
		 * Returns up to 8 emoji statuses, which must be shown right after the default Premium Badge in the emoji status list.
		 *
		 * <p> Returns {@link EmojiStatuses EmojiStatuses} </p>
		 *
		 *
		 * <p> Returns {@link EmojiStatuses EmojiStatuses} </p>
		**/

		/**
		 * Returns up to 8 emoji statuses, which must be shown right after the default Premium Badge in the emoji status list.
		 *
		 * <p> Returns {@link EmojiStatuses EmojiStatuses} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetThemedEmojiStatuses(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetThemedEmojiStatuses.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetThemedEmojiStatuses.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return GetThemedEmojiStatuses.CONSTRUCTOR;
		}
	}

	/**
	 * Returns a list of frequently used chats. Supported only if the chat
	 * info database is enabled.
	 * <p> Returns {@link Chats Chats} </p>
	**/
	public static final class GetTopChats extends Function<Chats> {


		/**
		 * Category of chats to be returned.
		**/
		public TopChatCategory category;

		/**
		 * The maximum number of chats to be returned; up to 30.
		**/
		public int limit;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -388410847;

		/**
		 * Returns a list of frequently used chats. Supported only if the chat info database is enabled.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		**/
		public GetTopChats() {}

		/**
		 * Returns a list of frequently used chats. Supported only if the chat info database is enabled.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		 *
		 * @param category Category of chats to be returned.
		 * @param limit The maximum number of chats to be returned; up to 30.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		**/
		public GetTopChats(TopChatCategory category, int limit) {
			this.category = category;
			this.limit = limit;
		}

		/**
		 * Returns a list of frequently used chats. Supported only if the chat info database is enabled.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetTopChats(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case TopChatCategoryUsers.CONSTRUCTOR: this.category = new TopChatCategoryUsers(input); break;
					case TopChatCategoryBots.CONSTRUCTOR: this.category = new TopChatCategoryBots(input); break;
					case TopChatCategoryGroups.CONSTRUCTOR: this.category = new TopChatCategoryGroups(input); break;
					case TopChatCategoryChannels.CONSTRUCTOR: this.category = new TopChatCategoryChannels(input); break;
					case TopChatCategoryInlineBots.CONSTRUCTOR: this.category = new TopChatCategoryInlineBots(input); break;
					case TopChatCategoryCalls.CONSTRUCTOR: this.category = new TopChatCategoryCalls(input); break;
					case TopChatCategoryForwardChats.CONSTRUCTOR: this.category = new TopChatCategoryForwardChats(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.limit = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetTopChats.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetTopChats.CONSTRUCTOR);
			if (this.category == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.category.serialize(output);
			}
			output.writeInt(this.limit);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetTopChats getTopChats = (GetTopChats) o;
			if (!Objects.equals(this.category, getTopChats.category)) {
				return false;
			}
			if (this.limit != getTopChats.limit) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.limit);
			result = result * 31 + (this.category == null ? 0 : this.category.hashCode());
			return result;
		}
	}

	/**
	 * Returns a list of trending sticker sets. For optimal performance, the
	 * number of returned sticker sets is chosen by TDLib.
	 * <p> Returns {@link TrendingStickerSets TrendingStickerSets} </p>
	**/
	public static final class GetTrendingStickerSets extends Function<TrendingStickerSets> {


		/**
		 * Type of the sticker sets to return.
		**/
		public StickerType stickerType;

		/**
		 * The offset from which to return the sticker sets; must be non-negative.
		**/
		public int offset;

		/**
		 * The maximum number of sticker sets to be returned; up to 100. For optimal performance, the number of returned sticker sets is chosen by TDLib and can be smaller than the specified limit, even if the end of the list has not been reached.
		**/
		public int limit;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -531085986;

		/**
		 * Returns a list of trending sticker sets. For optimal performance, the number of returned sticker sets is chosen by TDLib.
		 *
		 * <p> Returns {@link TrendingStickerSets TrendingStickerSets} </p>
		**/
		public GetTrendingStickerSets() {}

		/**
		 * Returns a list of trending sticker sets. For optimal performance, the number of returned sticker sets is chosen by TDLib.
		 *
		 * <p> Returns {@link TrendingStickerSets TrendingStickerSets} </p>
		 *
		 * @param stickerType Type of the sticker sets to return.
		 * @param offset The offset from which to return the sticker sets; must be non-negative.
		 * @param limit The maximum number of sticker sets to be returned; up to 100. For optimal performance, the number of returned sticker sets is chosen by TDLib and can be smaller than the specified limit, even if the end of the list has not been reached.
		 *
		 * <p> Returns {@link TrendingStickerSets TrendingStickerSets} </p>
		**/
		public GetTrendingStickerSets(StickerType stickerType, int offset, int limit) {
			this.stickerType = stickerType;
			this.offset = offset;
			this.limit = limit;
		}

		/**
		 * Returns a list of trending sticker sets. For optimal performance, the number of returned sticker sets is chosen by TDLib.
		 *
		 * <p> Returns {@link TrendingStickerSets TrendingStickerSets} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetTrendingStickerSets(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case StickerTypeRegular.CONSTRUCTOR: this.stickerType = new StickerTypeRegular(input); break;
					case StickerTypeMask.CONSTRUCTOR: this.stickerType = new StickerTypeMask(input); break;
					case StickerTypeCustomEmoji.CONSTRUCTOR: this.stickerType = new StickerTypeCustomEmoji(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.offset = input.readInt();
			this.limit = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetTrendingStickerSets.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetTrendingStickerSets.CONSTRUCTOR);
			if (this.stickerType == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.stickerType.serialize(output);
			}
			output.writeInt(this.offset);
			output.writeInt(this.limit);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetTrendingStickerSets getTrendingStickerSets = (GetTrendingStickerSets) o;
			if (!Objects.equals(this.stickerType, getTrendingStickerSets.stickerType)) {
				return false;
			}
			if (this.offset != getTrendingStickerSets.offset) {
				return false;
			}
			if (this.limit != getTrendingStickerSets.limit) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.offset);
			result = result * 31 + (this.stickerType == null ? 0 : this.stickerType.hashCode());
			return result;
		}
	}

	/**
	 * Returns information about a user by their identifier. This is an
	 * offline request if the current user is not a bot.
	 * <p> Returns {@link User User} </p>
	**/
	public static final class GetUser extends Function<User> {


		/**
		 * User identifier.
		**/
		public long userId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1117363211;

		/**
		 * Returns information about a user by their identifier. This is an offline request if the current user is not a bot.
		 *
		 * <p> Returns {@link User User} </p>
		**/
		public GetUser() {}

		/**
		 * Returns information about a user by their identifier. This is an offline request if the current user is not a bot.
		 *
		 * <p> Returns {@link User User} </p>
		 *
		 * @param userId User identifier.
		 *
		 * <p> Returns {@link User User} </p>
		**/
		public GetUser(long userId) {
			this.userId = userId;
		}

		/**
		 * Returns information about a user by their identifier. This is an offline request if the current user is not a bot.
		 *
		 * <p> Returns {@link User User} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetUser(DataInput input) throws IOException {
			this.userId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetUser.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetUser.CONSTRUCTOR);
			output.writeLong(this.userId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetUser getUser = (GetUser) o;
			if (this.userId != getUser.userId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.userId);
		}
	}

	/**
	 * Returns full information about a user by their identifier.
	 * <p> Returns {@link UserFullInfo UserFullInfo} </p>
	**/
	public static final class GetUserFullInfo extends Function<UserFullInfo> {


		/**
		 * User identifier.
		**/
		public long userId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -776823720;

		/**
		 * Returns full information about a user by their identifier.
		 *
		 * <p> Returns {@link UserFullInfo UserFullInfo} </p>
		**/
		public GetUserFullInfo() {}

		/**
		 * Returns full information about a user by their identifier.
		 *
		 * <p> Returns {@link UserFullInfo UserFullInfo} </p>
		 *
		 * @param userId User identifier.
		 *
		 * <p> Returns {@link UserFullInfo UserFullInfo} </p>
		**/
		public GetUserFullInfo(long userId) {
			this.userId = userId;
		}

		/**
		 * Returns full information about a user by their identifier.
		 *
		 * <p> Returns {@link UserFullInfo UserFullInfo} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetUserFullInfo(DataInput input) throws IOException {
			this.userId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetUserFullInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetUserFullInfo.CONSTRUCTOR);
			output.writeLong(this.userId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetUserFullInfo getUserFullInfo = (GetUserFullInfo) o;
			if (this.userId != getUserFullInfo.userId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.userId);
		}
	}

	/**
	 * Returns an HTTPS link, which can be used to get information about the
	 * current user.
	 * <p> Returns {@link UserLink UserLink} </p>
	**/
	public static final class GetUserLink extends Function<UserLink> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1226839270;

		/**
		 * Returns an HTTPS link, which can be used to get information about the current user.
		 *
		 * <p> Returns {@link UserLink UserLink} </p>
		**/
		public GetUserLink() {}

		/**
		 * Returns an HTTPS link, which can be used to get information about the current user.
		 *
		 * <p> Returns {@link UserLink UserLink} </p>
		 *
		 *
		 * <p> Returns {@link UserLink UserLink} </p>
		**/

		/**
		 * Returns an HTTPS link, which can be used to get information about the current user.
		 *
		 * <p> Returns {@link UserLink UserLink} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetUserLink(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetUserLink.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetUserLink.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return GetUserLink.CONSTRUCTOR;
		}
	}

	/**
	 * Returns the current privacy settings.
	 * <p> Returns {@link UserPrivacySettingRules UserPrivacySettingRules}
	 * </p>
	**/
	public static final class GetUserPrivacySettingRules extends Function<UserPrivacySettingRules> {


		/**
		 * The privacy setting.
		**/
		public UserPrivacySetting setting;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2077223311;

		/**
		 * Returns the current privacy settings.
		 *
		 * <p> Returns {@link UserPrivacySettingRules UserPrivacySettingRules} </p>
		**/
		public GetUserPrivacySettingRules() {}

		/**
		 * Returns the current privacy settings.
		 *
		 * <p> Returns {@link UserPrivacySettingRules UserPrivacySettingRules} </p>
		 *
		 * @param setting The privacy setting.
		 *
		 * <p> Returns {@link UserPrivacySettingRules UserPrivacySettingRules} </p>
		**/
		public GetUserPrivacySettingRules(UserPrivacySetting setting) {
			this.setting = setting;
		}

		/**
		 * Returns the current privacy settings.
		 *
		 * <p> Returns {@link UserPrivacySettingRules UserPrivacySettingRules} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetUserPrivacySettingRules(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case UserPrivacySettingShowStatus.CONSTRUCTOR: this.setting = new UserPrivacySettingShowStatus(input); break;
					case UserPrivacySettingShowProfilePhoto.CONSTRUCTOR: this.setting = new UserPrivacySettingShowProfilePhoto(input); break;
					case UserPrivacySettingShowLinkInForwardedMessages.CONSTRUCTOR: this.setting = new UserPrivacySettingShowLinkInForwardedMessages(input); break;
					case UserPrivacySettingShowPhoneNumber.CONSTRUCTOR: this.setting = new UserPrivacySettingShowPhoneNumber(input); break;
					case UserPrivacySettingAllowChatInvites.CONSTRUCTOR: this.setting = new UserPrivacySettingAllowChatInvites(input); break;
					case UserPrivacySettingAllowCalls.CONSTRUCTOR: this.setting = new UserPrivacySettingAllowCalls(input); break;
					case UserPrivacySettingAllowPeerToPeerCalls.CONSTRUCTOR: this.setting = new UserPrivacySettingAllowPeerToPeerCalls(input); break;
					case UserPrivacySettingAllowFindingByPhoneNumber.CONSTRUCTOR: this.setting = new UserPrivacySettingAllowFindingByPhoneNumber(input); break;
					case UserPrivacySettingAllowPrivateVoiceAndVideoNoteMessages.CONSTRUCTOR: this.setting = new UserPrivacySettingAllowPrivateVoiceAndVideoNoteMessages(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetUserPrivacySettingRules.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetUserPrivacySettingRules.CONSTRUCTOR);
			if (this.setting == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.setting.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetUserPrivacySettingRules getUserPrivacySettingRules = (GetUserPrivacySettingRules) o;
			if (!Objects.equals(this.setting, getUserPrivacySettingRules.setting)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.setting == null ? 0 : this.setting.hashCode();
		}
	}

	/**
	 * Returns the profile photos of a user. Personal and public photo
	 * aren&#039;t returned.
	 * <p> Returns {@link ChatPhotos ChatPhotos} </p>
	**/
	public static final class GetUserProfilePhotos extends Function<ChatPhotos> {


		/**
		 * User identifier.
		**/
		public long userId;

		/**
		 * The number of photos to skip; must be non-negative.
		**/
		public int offset;

		/**
		 * The maximum number of photos to be returned; up to 100.
		**/
		public int limit;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -908132798;

		/**
		 * Returns the profile photos of a user. Personal and public photo aren&#039;t returned.
		 *
		 * <p> Returns {@link ChatPhotos ChatPhotos} </p>
		**/
		public GetUserProfilePhotos() {}

		/**
		 * Returns the profile photos of a user. Personal and public photo aren&#039;t returned.
		 *
		 * <p> Returns {@link ChatPhotos ChatPhotos} </p>
		 *
		 * @param userId User identifier.
		 * @param offset The number of photos to skip; must be non-negative.
		 * @param limit The maximum number of photos to be returned; up to 100.
		 *
		 * <p> Returns {@link ChatPhotos ChatPhotos} </p>
		**/
		public GetUserProfilePhotos(long userId, int offset, int limit) {
			this.userId = userId;
			this.offset = offset;
			this.limit = limit;
		}

		/**
		 * Returns the profile photos of a user. Personal and public photo aren&#039;t returned.
		 *
		 * <p> Returns {@link ChatPhotos ChatPhotos} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetUserProfilePhotos(DataInput input) throws IOException {
			this.userId = input.readLong();
			this.offset = input.readInt();
			this.limit = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetUserProfilePhotos.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetUserProfilePhotos.CONSTRUCTOR);
			output.writeLong(this.userId);
			output.writeInt(this.offset);
			output.writeInt(this.limit);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetUserProfilePhotos getUserProfilePhotos = (GetUserProfilePhotos) o;
			if (this.userId != getUserProfilePhotos.userId) {
				return false;
			}
			if (this.offset != getUserProfilePhotos.offset) {
				return false;
			}
			if (this.limit != getUserProfilePhotos.limit) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.userId);
			return result;
		}
	}

	/**
	 * Returns support information for the given user; for Telegram support
	 * only.
	 * <p> Returns {@link UserSupportInfo UserSupportInfo} </p>
	**/
	public static final class GetUserSupportInfo extends Function<UserSupportInfo> {


		/**
		 * User identifier.
		**/
		public long userId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1957008133;

		/**
		 * Returns support information for the given user; for Telegram support only.
		 *
		 * <p> Returns {@link UserSupportInfo UserSupportInfo} </p>
		**/
		public GetUserSupportInfo() {}

		/**
		 * Returns support information for the given user; for Telegram support only.
		 *
		 * <p> Returns {@link UserSupportInfo UserSupportInfo} </p>
		 *
		 * @param userId User identifier.
		 *
		 * <p> Returns {@link UserSupportInfo UserSupportInfo} </p>
		**/
		public GetUserSupportInfo(long userId) {
			this.userId = userId;
		}

		/**
		 * Returns support information for the given user; for Telegram support only.
		 *
		 * <p> Returns {@link UserSupportInfo UserSupportInfo} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetUserSupportInfo(DataInput input) throws IOException {
			this.userId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetUserSupportInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetUserSupportInfo.CONSTRUCTOR);
			output.writeLong(this.userId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetUserSupportInfo getUserSupportInfo = (GetUserSupportInfo) o;
			if (this.userId != getUserSupportInfo.userId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.userId);
		}
	}

	/**
	 * Returns list of participant identifiers, on whose behalf a video chat
	 * in the chat can be joined.
	 * <p> Returns {@link MessageSenders MessageSenders} </p>
	**/
	public static final class GetVideoChatAvailableParticipants extends Function<MessageSenders> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1000496379;

		/**
		 * Returns list of participant identifiers, on whose behalf a video chat in the chat can be joined.
		 *
		 * <p> Returns {@link MessageSenders MessageSenders} </p>
		**/
		public GetVideoChatAvailableParticipants() {}

		/**
		 * Returns list of participant identifiers, on whose behalf a video chat in the chat can be joined.
		 *
		 * <p> Returns {@link MessageSenders MessageSenders} </p>
		 *
		 * @param chatId Chat identifier.
		 *
		 * <p> Returns {@link MessageSenders MessageSenders} </p>
		**/
		public GetVideoChatAvailableParticipants(long chatId) {
			this.chatId = chatId;
		}

		/**
		 * Returns list of participant identifiers, on whose behalf a video chat in the chat can be joined.
		 *
		 * <p> Returns {@link MessageSenders MessageSenders} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetVideoChatAvailableParticipants(DataInput input) throws IOException {
			this.chatId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetVideoChatAvailableParticipants.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetVideoChatAvailableParticipants.CONSTRUCTOR);
			output.writeLong(this.chatId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetVideoChatAvailableParticipants getVideoChatAvailableParticipants = (GetVideoChatAvailableParticipants) o;
			if (this.chatId != getVideoChatAvailableParticipants.chatId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.chatId);
		}
	}

	/**
	 * Returns RTMP URL for streaming to the chat; requires creator
	 * privileges.
	 * <p> Returns {@link RtmpUrl RtmpUrl} </p>
	**/
	public static final class GetVideoChatRtmpUrl extends Function<RtmpUrl> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1210784543;

		/**
		 * Returns RTMP URL for streaming to the chat; requires creator privileges.
		 *
		 * <p> Returns {@link RtmpUrl RtmpUrl} </p>
		**/
		public GetVideoChatRtmpUrl() {}

		/**
		 * Returns RTMP URL for streaming to the chat; requires creator privileges.
		 *
		 * <p> Returns {@link RtmpUrl RtmpUrl} </p>
		 *
		 * @param chatId Chat identifier.
		 *
		 * <p> Returns {@link RtmpUrl RtmpUrl} </p>
		**/
		public GetVideoChatRtmpUrl(long chatId) {
			this.chatId = chatId;
		}

		/**
		 * Returns RTMP URL for streaming to the chat; requires creator privileges.
		 *
		 * <p> Returns {@link RtmpUrl RtmpUrl} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetVideoChatRtmpUrl(DataInput input) throws IOException {
			this.chatId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetVideoChatRtmpUrl.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetVideoChatRtmpUrl.CONSTRUCTOR);
			output.writeLong(this.chatId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetVideoChatRtmpUrl getVideoChatRtmpUrl = (GetVideoChatRtmpUrl) o;
			if (this.chatId != getVideoChatRtmpUrl.chatId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.chatId);
		}
	}

	/**
	 * Returns an HTTPS URL of a Web App to open after a link of the type
	 * internalLinkTypeWebApp is clicked.
	 * <p> Returns {@link HttpUrl HttpUrl} </p>
	**/
	public static final class GetWebAppLinkUrl extends Function<HttpUrl> {


		/**
		 * Identifier of the chat in which the link was clicked; pass 0 if none.
		**/
		public long chatId;

		/**
		 * Identifier of the target bot.
		**/
		public long botUserId;

		/**
		 * Short name of the Web App.
		**/
		public String webAppShortName;

		/**
		 * Start parameter from internalLinkTypeWebApp.
		**/
		public String startParameter;

		/**
		 * Preferred Web App theme; pass null to use the default theme.
		**/
		public ThemeParameters theme;

		/**
		 * Short name of the application; 0-64 English letters, digits, and underscores.
		**/
		public String applicationName;

		/**
		 * Pass true if the current user allowed the bot to send them messages.
		**/
		public boolean allowWriteAccess;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1326379980;

		/**
		 * Returns an HTTPS URL of a Web App to open after a link of the type internalLinkTypeWebApp is clicked.
		 *
		 * <p> Returns {@link HttpUrl HttpUrl} </p>
		**/
		public GetWebAppLinkUrl() {}

		/**
		 * Returns an HTTPS URL of a Web App to open after a link of the type internalLinkTypeWebApp is clicked.
		 *
		 * <p> Returns {@link HttpUrl HttpUrl} </p>
		 *
		 * @param chatId Identifier of the chat in which the link was clicked; pass 0 if none.
		 * @param botUserId Identifier of the target bot.
		 * @param webAppShortName Short name of the Web App.
		 * @param startParameter Start parameter from internalLinkTypeWebApp.
		 * @param theme Preferred Web App theme; pass null to use the default theme.
		 * @param applicationName Short name of the application; 0-64 English letters, digits, and underscores.
		 * @param allowWriteAccess Pass true if the current user allowed the bot to send them messages.
		 *
		 * <p> Returns {@link HttpUrl HttpUrl} </p>
		**/
		public GetWebAppLinkUrl(long chatId,
				long botUserId,
				String webAppShortName,
				String startParameter,
				ThemeParameters theme,
				String applicationName,
				boolean allowWriteAccess) {
			this.chatId = chatId;
			this.botUserId = botUserId;
			this.webAppShortName = webAppShortName;
			this.startParameter = startParameter;
			this.theme = theme;
			this.applicationName = applicationName;
			this.allowWriteAccess = allowWriteAccess;
		}

		/**
		 * Returns an HTTPS URL of a Web App to open after a link of the type internalLinkTypeWebApp is clicked.
		 *
		 * <p> Returns {@link HttpUrl HttpUrl} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetWebAppLinkUrl(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.botUserId = input.readLong();
			if (input.readBoolean()) {
				byte[] webAppShortNameTmp = new byte[input.readInt()];
				input.readFully(webAppShortNameTmp);
				this.webAppShortName = new String(webAppShortNameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] startParameterTmp = new byte[input.readInt()];
				input.readFully(startParameterTmp);
				this.startParameter = new String(startParameterTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (ThemeParameters.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.theme = new ThemeParameters(input);
			}
			if (input.readBoolean()) {
				byte[] applicationNameTmp = new byte[input.readInt()];
				input.readFully(applicationNameTmp);
				this.applicationName = new String(applicationNameTmp, StandardCharsets.UTF_8);
			}
			this.allowWriteAccess = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetWebAppLinkUrl.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetWebAppLinkUrl.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.botUserId);
			if (this.webAppShortName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] webAppShortNameTmp = this.webAppShortName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(webAppShortNameTmp.length);
				output.write(webAppShortNameTmp);
			}
			if (this.startParameter == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] startParameterTmp = this.startParameter.getBytes(StandardCharsets.UTF_8);
				output.writeInt(startParameterTmp.length);
				output.write(startParameterTmp);
			}
			if (this.theme == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.theme.serialize(output);
			}
			if (this.applicationName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] applicationNameTmp = this.applicationName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(applicationNameTmp.length);
				output.write(applicationNameTmp);
			}
			output.writeBoolean(this.allowWriteAccess);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetWebAppLinkUrl getWebAppLinkUrl = (GetWebAppLinkUrl) o;
			if (this.chatId != getWebAppLinkUrl.chatId) {
				return false;
			}
			if (this.botUserId != getWebAppLinkUrl.botUserId) {
				return false;
			}
			if (this.webAppShortName != getWebAppLinkUrl.webAppShortName) {
				return false;
			}
			if (this.startParameter != getWebAppLinkUrl.startParameter) {
				return false;
			}
			if (!Objects.equals(this.theme, getWebAppLinkUrl.theme)) {
				return false;
			}
			if (this.applicationName != getWebAppLinkUrl.applicationName) {
				return false;
			}
			if (this.allowWriteAccess != getWebAppLinkUrl.allowWriteAccess) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.webAppShortName == null ? 0 : this.webAppShortName.hashCode());
			result = result * 31 + (this.startParameter == null ? 0 : this.startParameter.hashCode());
			result = result * 31 + (this.theme == null ? 0 : this.theme.hashCode());
			result = result * 31 + (this.applicationName == null ? 0 : this.applicationName.hashCode());
			return result;
		}
	}

	/**
	 * Returns an HTTPS URL of a Web App to open after
	 * keyboardButtonTypeWebApp or inlineQueryResultsButtonTypeWebApp button
	 * is pressed.
	 * <p> Returns {@link HttpUrl HttpUrl} </p>
	**/
	public static final class GetWebAppUrl extends Function<HttpUrl> {


		/**
		 * Identifier of the target bot.
		**/
		public long botUserId;

		/**
		 * The URL from the keyboardButtonTypeWebApp or inlineQueryResultsButtonTypeWebApp button.
		**/
		public String url;

		/**
		 * Preferred Web App theme; pass null to use the default theme.
		**/
		public ThemeParameters theme;

		/**
		 * Short name of the application; 0-64 English letters, digits, and underscores.
		**/
		public String applicationName;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1690578110;

		/**
		 * Returns an HTTPS URL of a Web App to open after keyboardButtonTypeWebApp or inlineQueryResultsButtonTypeWebApp button is pressed.
		 *
		 * <p> Returns {@link HttpUrl HttpUrl} </p>
		**/
		public GetWebAppUrl() {}

		/**
		 * Returns an HTTPS URL of a Web App to open after keyboardButtonTypeWebApp or inlineQueryResultsButtonTypeWebApp button is pressed.
		 *
		 * <p> Returns {@link HttpUrl HttpUrl} </p>
		 *
		 * @param botUserId Identifier of the target bot.
		 * @param url The URL from the keyboardButtonTypeWebApp or inlineQueryResultsButtonTypeWebApp button.
		 * @param theme Preferred Web App theme; pass null to use the default theme.
		 * @param applicationName Short name of the application; 0-64 English letters, digits, and underscores.
		 *
		 * <p> Returns {@link HttpUrl HttpUrl} </p>
		**/
		public GetWebAppUrl(long botUserId,
				String url,
				ThemeParameters theme,
				String applicationName) {
			this.botUserId = botUserId;
			this.url = url;
			this.theme = theme;
			this.applicationName = applicationName;
		}

		/**
		 * Returns an HTTPS URL of a Web App to open after keyboardButtonTypeWebApp or inlineQueryResultsButtonTypeWebApp button is pressed.
		 *
		 * <p> Returns {@link HttpUrl HttpUrl} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetWebAppUrl(DataInput input) throws IOException {
			this.botUserId = input.readLong();
			if (input.readBoolean()) {
				byte[] urlTmp = new byte[input.readInt()];
				input.readFully(urlTmp);
				this.url = new String(urlTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (ThemeParameters.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.theme = new ThemeParameters(input);
			}
			if (input.readBoolean()) {
				byte[] applicationNameTmp = new byte[input.readInt()];
				input.readFully(applicationNameTmp);
				this.applicationName = new String(applicationNameTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetWebAppUrl.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetWebAppUrl.CONSTRUCTOR);
			output.writeLong(this.botUserId);
			if (this.url == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] urlTmp = this.url.getBytes(StandardCharsets.UTF_8);
				output.writeInt(urlTmp.length);
				output.write(urlTmp);
			}
			if (this.theme == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.theme.serialize(output);
			}
			if (this.applicationName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] applicationNameTmp = this.applicationName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(applicationNameTmp.length);
				output.write(applicationNameTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetWebAppUrl getWebAppUrl = (GetWebAppUrl) o;
			if (this.botUserId != getWebAppUrl.botUserId) {
				return false;
			}
			if (this.url != getWebAppUrl.url) {
				return false;
			}
			if (!Objects.equals(this.theme, getWebAppUrl.theme)) {
				return false;
			}
			if (this.applicationName != getWebAppUrl.applicationName) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.botUserId);
			result = result * 31 + (this.url == null ? 0 : this.url.hashCode());
			result = result * 31 + (this.theme == null ? 0 : this.theme.hashCode());
			result = result * 31 + (this.applicationName == null ? 0 : this.applicationName.hashCode());
			return result;
		}
	}

	/**
	 * Returns an instant view version of a web page if available. Returns a
	 * 404 error if the web page has no instant view page.
	 * <p> Returns {@link WebPageInstantView WebPageInstantView} </p>
	**/
	public static final class GetWebPageInstantView extends Function<WebPageInstantView> {


		/**
		 * The web page URL.
		**/
		public String url;

		/**
		 * Pass true to get full instant view for the web page.
		**/
		public boolean forceFull;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1962649975;

		/**
		 * Returns an instant view version of a web page if available. Returns a 404 error if the web page has no instant view page.
		 *
		 * <p> Returns {@link WebPageInstantView WebPageInstantView} </p>
		**/
		public GetWebPageInstantView() {}

		/**
		 * Returns an instant view version of a web page if available. Returns a 404 error if the web page has no instant view page.
		 *
		 * <p> Returns {@link WebPageInstantView WebPageInstantView} </p>
		 *
		 * @param url The web page URL.
		 * @param forceFull Pass true to get full instant view for the web page.
		 *
		 * <p> Returns {@link WebPageInstantView WebPageInstantView} </p>
		**/
		public GetWebPageInstantView(String url, boolean forceFull) {
			this.url = url;
			this.forceFull = forceFull;
		}

		/**
		 * Returns an instant view version of a web page if available. Returns a 404 error if the web page has no instant view page.
		 *
		 * <p> Returns {@link WebPageInstantView WebPageInstantView} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetWebPageInstantView(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] urlTmp = new byte[input.readInt()];
				input.readFully(urlTmp);
				this.url = new String(urlTmp, StandardCharsets.UTF_8);
			}
			this.forceFull = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetWebPageInstantView.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetWebPageInstantView.CONSTRUCTOR);
			if (this.url == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] urlTmp = this.url.getBytes(StandardCharsets.UTF_8);
				output.writeInt(urlTmp.length);
				output.write(urlTmp);
			}
			output.writeBoolean(this.forceFull);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetWebPageInstantView getWebPageInstantView = (GetWebPageInstantView) o;
			if (this.url != getWebPageInstantView.url) {
				return false;
			}
			if (this.forceFull != getWebPageInstantView.forceFull) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.forceFull);
			result = result * 31 + (this.url == null ? 0 : this.url.hashCode());
			return result;
		}
	}

	/**
	 * Returns a web page preview by the text of the message. Do not call
	 * this function too often. Returns a 404 error if the web page has no
	 * preview.
	 * <p> Returns {@link WebPage WebPage} </p>
	**/
	public static final class GetWebPagePreview extends Function<WebPage> {


		/**
		 * Message text with formatting.
		**/
		public FormattedText text;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 573441580;

		/**
		 * Returns a web page preview by the text of the message. Do not call this function too often. Returns a 404 error if the web page has no preview.
		 *
		 * <p> Returns {@link WebPage WebPage} </p>
		**/
		public GetWebPagePreview() {}

		/**
		 * Returns a web page preview by the text of the message. Do not call this function too often. Returns a 404 error if the web page has no preview.
		 *
		 * <p> Returns {@link WebPage WebPage} </p>
		 *
		 * @param text Message text with formatting.
		 *
		 * <p> Returns {@link WebPage WebPage} </p>
		**/
		public GetWebPagePreview(FormattedText text) {
			this.text = text;
		}

		/**
		 * Returns a web page preview by the text of the message. Do not call this function too often. Returns a 404 error if the web page has no preview.
		 *
		 * <p> Returns {@link WebPage WebPage} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public GetWebPagePreview(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (FormattedText.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.text = new FormattedText(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return GetWebPagePreview.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(GetWebPagePreview.CONSTRUCTOR);
			if (this.text == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.text.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			GetWebPagePreview getWebPagePreview = (GetWebPagePreview) o;
			if (!Objects.equals(this.text, getWebPagePreview.text)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.text == null ? 0 : this.text.hashCode();
		}
	}

	/**
	 * Hides a suggested action.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class HideSuggestedAction extends Function<Ok> {


		/**
		 * Suggested action to hide.
		**/
		public SuggestedAction action;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1561384065;

		/**
		 * Hides a suggested action.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public HideSuggestedAction() {}

		/**
		 * Hides a suggested action.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param action Suggested action to hide.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public HideSuggestedAction(SuggestedAction action) {
			this.action = action;
		}

		/**
		 * Hides a suggested action.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public HideSuggestedAction(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case SuggestedActionEnableArchiveAndMuteNewChats.CONSTRUCTOR: this.action = new SuggestedActionEnableArchiveAndMuteNewChats(input); break;
					case SuggestedActionCheckPassword.CONSTRUCTOR: this.action = new SuggestedActionCheckPassword(input); break;
					case SuggestedActionCheckPhoneNumber.CONSTRUCTOR: this.action = new SuggestedActionCheckPhoneNumber(input); break;
					case SuggestedActionViewChecksHint.CONSTRUCTOR: this.action = new SuggestedActionViewChecksHint(input); break;
					case SuggestedActionConvertToBroadcastGroup.CONSTRUCTOR: this.action = new SuggestedActionConvertToBroadcastGroup(input); break;
					case SuggestedActionSetPassword.CONSTRUCTOR: this.action = new SuggestedActionSetPassword(input); break;
					case SuggestedActionUpgradePremium.CONSTRUCTOR: this.action = new SuggestedActionUpgradePremium(input); break;
					case SuggestedActionSubscribeToAnnualPremium.CONSTRUCTOR: this.action = new SuggestedActionSubscribeToAnnualPremium(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return HideSuggestedAction.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(HideSuggestedAction.CONSTRUCTOR);
			if (this.action == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.action.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			HideSuggestedAction hideSuggestedAction = (HideSuggestedAction) o;
			if (!Objects.equals(this.action, hideSuggestedAction.action)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.action == null ? 0 : this.action.hashCode();
		}
	}

	/**
	 * Adds new contacts or edits existing contacts by their phone numbers;
	 * contacts&#039; user identifiers are ignored.
	 * <p> Returns {@link ImportedContacts ImportedContacts} </p>
	**/
	public static final class ImportContacts extends Function<ImportedContacts> {


		/**
		 * The list of contacts to import or edit; contacts&#039; vCard are ignored and are not imported.
		**/
		public Contact[] contacts;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -215132767;

		/**
		 * Adds new contacts or edits existing contacts by their phone numbers; contacts&#039; user identifiers are ignored.
		 *
		 * <p> Returns {@link ImportedContacts ImportedContacts} </p>
		**/
		public ImportContacts() {}

		/**
		 * Adds new contacts or edits existing contacts by their phone numbers; contacts&#039; user identifiers are ignored.
		 *
		 * <p> Returns {@link ImportedContacts ImportedContacts} </p>
		 *
		 * @param contacts The list of contacts to import or edit; contacts&#039; vCard are ignored and are not imported.
		 *
		 * <p> Returns {@link ImportedContacts ImportedContacts} </p>
		**/
		public ImportContacts(Contact[] contacts) {
			this.contacts = contacts;
		}

		/**
		 * Adds new contacts or edits existing contacts by their phone numbers; contacts&#039; user identifiers are ignored.
		 *
		 * <p> Returns {@link ImportedContacts ImportedContacts} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ImportContacts(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.contacts = new Contact[input.readInt()];
				for (int i = 0; i < this.contacts.length; i++) {
					if (Contact.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.contacts[i] = new Contact(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ImportContacts.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ImportContacts.CONSTRUCTOR);
			if (this.contacts == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.contacts.length);
				for (int i = 0; i < this.contacts.length; i++) {
					this.contacts[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ImportContacts importContacts = (ImportContacts) o;
			if (!Arrays.equals(this.contacts, importContacts.contacts)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.contacts);
		}
	}

	/**
	 * Imports messages exported from another app.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ImportMessages extends Function<Ok> {


		/**
		 * Identifier of a chat to which the messages will be imported. It must be an identifier of a private chat with a mutual contact or an identifier of a supergroup chat with canChangeInfo administrator right.
		**/
		public long chatId;

		/**
		 * File with messages to import. Only inputFileLocal and inputFileGenerated are supported. The file must not be previously uploaded.
		**/
		public InputFile messageFile;

		/**
		 * Files used in the imported messages. Only inputFileLocal and inputFileGenerated are supported. The files must not be previously uploaded.
		**/
		public InputFile[] attachedFiles;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1864116784;

		/**
		 * Imports messages exported from another app.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ImportMessages() {}

		/**
		 * Imports messages exported from another app.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Identifier of a chat to which the messages will be imported. It must be an identifier of a private chat with a mutual contact or an identifier of a supergroup chat with canChangeInfo administrator right.
		 * @param messageFile File with messages to import. Only inputFileLocal and inputFileGenerated are supported. The file must not be previously uploaded.
		 * @param attachedFiles Files used in the imported messages. Only inputFileLocal and inputFileGenerated are supported. The files must not be previously uploaded.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ImportMessages(long chatId,
				InputFile messageFile,
				InputFile[] attachedFiles) {
			this.chatId = chatId;
			this.messageFile = messageFile;
			this.attachedFiles = attachedFiles;
		}

		/**
		 * Imports messages exported from another app.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ImportMessages(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputFileId.CONSTRUCTOR: this.messageFile = new InputFileId(input); break;
					case InputFileRemote.CONSTRUCTOR: this.messageFile = new InputFileRemote(input); break;
					case InputFileLocal.CONSTRUCTOR: this.messageFile = new InputFileLocal(input); break;
					case InputFileGenerated.CONSTRUCTOR: this.messageFile = new InputFileGenerated(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				this.attachedFiles = new InputFile[input.readInt()];
				for (int i = 0; i < this.attachedFiles.length; i++) {
					switch(input.readInt()) {
						case InputFileId.CONSTRUCTOR: this.attachedFiles[i] = new InputFileId(input); break;
						case InputFileRemote.CONSTRUCTOR: this.attachedFiles[i] = new InputFileRemote(input); break;
						case InputFileLocal.CONSTRUCTOR: this.attachedFiles[i] = new InputFileLocal(input); break;
						case InputFileGenerated.CONSTRUCTOR: this.attachedFiles[i] = new InputFileGenerated(input); break;
						default: {
							throw new UnsupportedOperationException();
						}
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ImportMessages.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ImportMessages.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.messageFile == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.messageFile.serialize(output);
			}
			if (this.attachedFiles == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.attachedFiles.length);
				for (int i = 0; i < this.attachedFiles.length; i++) {
					this.attachedFiles[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ImportMessages importMessages = (ImportMessages) o;
			if (this.chatId != importMessages.chatId) {
				return false;
			}
			if (!Objects.equals(this.messageFile, importMessages.messageFile)) {
				return false;
			}
			if (!Arrays.equals(this.attachedFiles, importMessages.attachedFiles)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.messageFile == null ? 0 : this.messageFile.hashCode());
			result = result * 31 + (Arrays.hashCode(this.attachedFiles));
			return result;
		}
	}

	/**
	 * Invites users to an active group call. Sends a service message of
	 * type messageInviteToGroupCall for video chats.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class InviteGroupCallParticipants extends Function<Ok> {


		/**
		 * Group call identifier.
		**/
		public int groupCallId;

		/**
		 * User identifiers. At most 10 users can be invited simultaneously.
		**/
		public long[] userIds;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1867097679;

		/**
		 * Invites users to an active group call. Sends a service message of type messageInviteToGroupCall for video chats.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public InviteGroupCallParticipants() {}

		/**
		 * Invites users to an active group call. Sends a service message of type messageInviteToGroupCall for video chats.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param groupCallId Group call identifier.
		 * @param userIds User identifiers. At most 10 users can be invited simultaneously.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public InviteGroupCallParticipants(int groupCallId, long[] userIds) {
			this.groupCallId = groupCallId;
			this.userIds = userIds;
		}

		/**
		 * Invites users to an active group call. Sends a service message of type messageInviteToGroupCall for video chats.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public InviteGroupCallParticipants(DataInput input) throws IOException {
			this.groupCallId = input.readInt();
			if (input.readBoolean()) {
				this.userIds = new long[input.readInt()];
				for (int i = 0; i < this.userIds.length; i++) {
					this.userIds[i] = input.readLong();
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return InviteGroupCallParticipants.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(InviteGroupCallParticipants.CONSTRUCTOR);
			output.writeInt(this.groupCallId);
			if (this.userIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.userIds.length);
				for (int i = 0; i < this.userIds.length; i++) {
					output.writeLong(this.userIds[i]);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			InviteGroupCallParticipants inviteGroupCallParticipants = (InviteGroupCallParticipants) o;
			if (this.groupCallId != inviteGroupCallParticipants.groupCallId) {
				return false;
			}
			if (!Arrays.equals(this.userIds, inviteGroupCallParticipants.userIds)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.groupCallId);
			result = result * 31 + (Arrays.hashCode(this.userIds));
			return result;
		}
	}

	/**
	 * Adds the current user as a new member to a chat. Private and secret
	 * chats can&#039;t be joined using this method. May return an error
	 * with a message &quot;INVITE_REQUEST_SENT&quot; if only a join request
	 * was created.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class JoinChat extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 326769313;

		/**
		 * Adds the current user as a new member to a chat. Private and secret chats can&#039;t be joined using this method. May return an error with a message &quot;INVITE_REQUEST_SENT&quot; if only a join request was created.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public JoinChat() {}

		/**
		 * Adds the current user as a new member to a chat. Private and secret chats can&#039;t be joined using this method. May return an error with a message &quot;INVITE_REQUEST_SENT&quot; if only a join request was created.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public JoinChat(long chatId) {
			this.chatId = chatId;
		}

		/**
		 * Adds the current user as a new member to a chat. Private and secret chats can&#039;t be joined using this method. May return an error with a message &quot;INVITE_REQUEST_SENT&quot; if only a join request was created.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public JoinChat(DataInput input) throws IOException {
			this.chatId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return JoinChat.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(JoinChat.CONSTRUCTOR);
			output.writeLong(this.chatId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			JoinChat joinChat = (JoinChat) o;
			if (this.chatId != joinChat.chatId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.chatId);
		}
	}

	/**
	 * Uses an invite link to add the current user to the chat if possible.
	 * May return an error with a message &quot;INVITE_REQUEST_SENT&quot; if
	 * only a join request was created.
	 * <p> Returns {@link Chat Chat} </p>
	**/
	public static final class JoinChatByInviteLink extends Function<Chat> {


		/**
		 * Invite link to use.
		**/
		public String inviteLink;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1049973882;

		/**
		 * Uses an invite link to add the current user to the chat if possible. May return an error with a message &quot;INVITE_REQUEST_SENT&quot; if only a join request was created.
		 *
		 * <p> Returns {@link Chat Chat} </p>
		**/
		public JoinChatByInviteLink() {}

		/**
		 * Uses an invite link to add the current user to the chat if possible. May return an error with a message &quot;INVITE_REQUEST_SENT&quot; if only a join request was created.
		 *
		 * <p> Returns {@link Chat Chat} </p>
		 *
		 * @param inviteLink Invite link to use.
		 *
		 * <p> Returns {@link Chat Chat} </p>
		**/
		public JoinChatByInviteLink(String inviteLink) {
			this.inviteLink = inviteLink;
		}

		/**
		 * Uses an invite link to add the current user to the chat if possible. May return an error with a message &quot;INVITE_REQUEST_SENT&quot; if only a join request was created.
		 *
		 * <p> Returns {@link Chat Chat} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public JoinChatByInviteLink(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] inviteLinkTmp = new byte[input.readInt()];
				input.readFully(inviteLinkTmp);
				this.inviteLink = new String(inviteLinkTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return JoinChatByInviteLink.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(JoinChatByInviteLink.CONSTRUCTOR);
			if (this.inviteLink == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] inviteLinkTmp = this.inviteLink.getBytes(StandardCharsets.UTF_8);
				output.writeInt(inviteLinkTmp.length);
				output.write(inviteLinkTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			JoinChatByInviteLink joinChatByInviteLink = (JoinChatByInviteLink) o;
			if (this.inviteLink != joinChatByInviteLink.inviteLink) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.inviteLink == null ? 0 : this.inviteLink.hashCode();
		}
	}

	/**
	 * Joins an active group call. Returns join response payload for tgcalls.
	 * <p> Returns {@link Text Text} </p>
	**/
	public static final class JoinGroupCall extends Function<Text> {


		/**
		 * Group call identifier.
		**/
		public int groupCallId;

		/**
		 * Identifier of a group call participant, which will be used to join the call; pass null to join as self; video chats only.
		**/
		public MessageSender participantId;

		/**
		 * Caller audio channel synchronization source identifier; received from tgcalls.
		**/
		public int audioSourceId;

		/**
		 * Group call join payload; received from tgcalls.
		**/
		public String payload;

		/**
		 * Pass true to join the call with muted microphone.
		**/
		public boolean isMuted;

		/**
		 * Pass true if the user&#039;s video is enabled.
		**/
		public boolean isMyVideoEnabled;

		/**
		 * If non-empty, invite hash to be used to join the group call without being muted by administrators.
		**/
		public String inviteHash;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1043773467;

		/**
		 * Joins an active group call. Returns join response payload for tgcalls.
		 *
		 * <p> Returns {@link Text Text} </p>
		**/
		public JoinGroupCall() {}

		/**
		 * Joins an active group call. Returns join response payload for tgcalls.
		 *
		 * <p> Returns {@link Text Text} </p>
		 *
		 * @param groupCallId Group call identifier.
		 * @param participantId Identifier of a group call participant, which will be used to join the call; pass null to join as self; video chats only.
		 * @param audioSourceId Caller audio channel synchronization source identifier; received from tgcalls.
		 * @param payload Group call join payload; received from tgcalls.
		 * @param isMuted Pass true to join the call with muted microphone.
		 * @param isMyVideoEnabled Pass true if the user&#039;s video is enabled.
		 * @param inviteHash If non-empty, invite hash to be used to join the group call without being muted by administrators.
		 *
		 * <p> Returns {@link Text Text} </p>
		**/
		public JoinGroupCall(int groupCallId,
				MessageSender participantId,
				int audioSourceId,
				String payload,
				boolean isMuted,
				boolean isMyVideoEnabled,
				String inviteHash) {
			this.groupCallId = groupCallId;
			this.participantId = participantId;
			this.audioSourceId = audioSourceId;
			this.payload = payload;
			this.isMuted = isMuted;
			this.isMyVideoEnabled = isMyVideoEnabled;
			this.inviteHash = inviteHash;
		}

		/**
		 * Joins an active group call. Returns join response payload for tgcalls.
		 *
		 * <p> Returns {@link Text Text} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public JoinGroupCall(DataInput input) throws IOException {
			this.groupCallId = input.readInt();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case MessageSenderUser.CONSTRUCTOR: this.participantId = new MessageSenderUser(input); break;
					case MessageSenderChat.CONSTRUCTOR: this.participantId = new MessageSenderChat(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.audioSourceId = input.readInt();
			if (input.readBoolean()) {
				byte[] payloadTmp = new byte[input.readInt()];
				input.readFully(payloadTmp);
				this.payload = new String(payloadTmp, StandardCharsets.UTF_8);
			}
			this.isMuted = input.readBoolean();
			this.isMyVideoEnabled = input.readBoolean();
			if (input.readBoolean()) {
				byte[] inviteHashTmp = new byte[input.readInt()];
				input.readFully(inviteHashTmp);
				this.inviteHash = new String(inviteHashTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return JoinGroupCall.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(JoinGroupCall.CONSTRUCTOR);
			output.writeInt(this.groupCallId);
			if (this.participantId == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.participantId.serialize(output);
			}
			output.writeInt(this.audioSourceId);
			if (this.payload == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] payloadTmp = this.payload.getBytes(StandardCharsets.UTF_8);
				output.writeInt(payloadTmp.length);
				output.write(payloadTmp);
			}
			output.writeBoolean(this.isMuted);
			output.writeBoolean(this.isMyVideoEnabled);
			if (this.inviteHash == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] inviteHashTmp = this.inviteHash.getBytes(StandardCharsets.UTF_8);
				output.writeInt(inviteHashTmp.length);
				output.write(inviteHashTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			JoinGroupCall joinGroupCall = (JoinGroupCall) o;
			if (this.groupCallId != joinGroupCall.groupCallId) {
				return false;
			}
			if (!Objects.equals(this.participantId, joinGroupCall.participantId)) {
				return false;
			}
			if (this.audioSourceId != joinGroupCall.audioSourceId) {
				return false;
			}
			if (this.payload != joinGroupCall.payload) {
				return false;
			}
			if (this.isMuted != joinGroupCall.isMuted) {
				return false;
			}
			if (this.isMyVideoEnabled != joinGroupCall.isMyVideoEnabled) {
				return false;
			}
			if (this.inviteHash != joinGroupCall.inviteHash) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.groupCallId);
			result = result * 31 + (this.participantId == null ? 0 : this.participantId.hashCode());
			result = result * 31 + (this.payload == null ? 0 : this.payload.hashCode());
			result = result * 31 + (this.inviteHash == null ? 0 : this.inviteHash.hashCode());
			return result;
		}
	}

	/**
	 * Removes the current user from chat members. Private and secret chats
	 * can&#039;t be left using this method.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class LeaveChat extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1825080735;

		/**
		 * Removes the current user from chat members. Private and secret chats can&#039;t be left using this method.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public LeaveChat() {}

		/**
		 * Removes the current user from chat members. Private and secret chats can&#039;t be left using this method.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public LeaveChat(long chatId) {
			this.chatId = chatId;
		}

		/**
		 * Removes the current user from chat members. Private and secret chats can&#039;t be left using this method.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public LeaveChat(DataInput input) throws IOException {
			this.chatId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return LeaveChat.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(LeaveChat.CONSTRUCTOR);
			output.writeLong(this.chatId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			LeaveChat leaveChat = (LeaveChat) o;
			if (this.chatId != leaveChat.chatId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.chatId);
		}
	}

	/**
	 * Leaves a group call.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class LeaveGroupCall extends Function<Ok> {


		/**
		 * Group call identifier.
		**/
		public int groupCallId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 980152233;

		/**
		 * Leaves a group call.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public LeaveGroupCall() {}

		/**
		 * Leaves a group call.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param groupCallId Group call identifier.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public LeaveGroupCall(int groupCallId) {
			this.groupCallId = groupCallId;
		}

		/**
		 * Leaves a group call.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public LeaveGroupCall(DataInput input) throws IOException {
			this.groupCallId = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return LeaveGroupCall.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(LeaveGroupCall.CONSTRUCTOR);
			output.writeInt(this.groupCallId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			LeaveGroupCall leaveGroupCall = (LeaveGroupCall) o;
			if (this.groupCallId != leaveGroupCall.groupCallId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.groupCallId);
		}
	}

	/**
	 * Loads more chats from a chat list. The loaded chats and their
	 * positions in the chat list will be sent through updates. Chats are
	 * sorted by the pair (chat.position.order, chat.id) in descending
	 * order. Returns a 404 error if all chats have been loaded.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class LoadChats extends Function<Ok> {


		/**
		 * The chat list in which to load chats; pass null to load chats from the main chat list.
		**/
		public ChatList chatList;

		/**
		 * The maximum number of chats to be loaded. For optimal performance, the number of loaded chats is chosen by TDLib and can be smaller than the specified limit, even if the end of the list is not reached.
		**/
		public int limit;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1885635205;

		/**
		 * Loads more chats from a chat list. The loaded chats and their positions in the chat list will be sent through updates. Chats are sorted by the pair (chat.position.order, chat.id) in descending order. Returns a 404 error if all chats have been loaded.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public LoadChats() {}

		/**
		 * Loads more chats from a chat list. The loaded chats and their positions in the chat list will be sent through updates. Chats are sorted by the pair (chat.position.order, chat.id) in descending order. Returns a 404 error if all chats have been loaded.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatList The chat list in which to load chats; pass null to load chats from the main chat list.
		 * @param limit The maximum number of chats to be loaded. For optimal performance, the number of loaded chats is chosen by TDLib and can be smaller than the specified limit, even if the end of the list is not reached.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public LoadChats(ChatList chatList, int limit) {
			this.chatList = chatList;
			this.limit = limit;
		}

		/**
		 * Loads more chats from a chat list. The loaded chats and their positions in the chat list will be sent through updates. Chats are sorted by the pair (chat.position.order, chat.id) in descending order. Returns a 404 error if all chats have been loaded.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public LoadChats(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ChatListMain.CONSTRUCTOR: this.chatList = new ChatListMain(input); break;
					case ChatListArchive.CONSTRUCTOR: this.chatList = new ChatListArchive(input); break;
					case ChatListFolder.CONSTRUCTOR: this.chatList = new ChatListFolder(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.limit = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return LoadChats.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(LoadChats.CONSTRUCTOR);
			if (this.chatList == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.chatList.serialize(output);
			}
			output.writeInt(this.limit);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			LoadChats loadChats = (LoadChats) o;
			if (!Objects.equals(this.chatList, loadChats.chatList)) {
				return false;
			}
			if (this.limit != loadChats.limit) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.limit);
			result = result * 31 + (this.chatList == null ? 0 : this.chatList.hashCode());
			return result;
		}
	}

	/**
	 * Loads more participants of a group call. The loaded participants will
	 * be received through updates. Use the field
	 * groupCall.loadedAllParticipants to check whether all participants
	 * have already been loaded.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class LoadGroupCallParticipants extends Function<Ok> {


		/**
		 * Group call identifier. The group call must be previously received through getGroupCall and must be joined or being joined.
		**/
		public int groupCallId;

		/**
		 * The maximum number of participants to load; up to 100.
		**/
		public int limit;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 938720974;

		/**
		 * Loads more participants of a group call. The loaded participants will be received through updates. Use the field groupCall.loadedAllParticipants to check whether all participants have already been loaded.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public LoadGroupCallParticipants() {}

		/**
		 * Loads more participants of a group call. The loaded participants will be received through updates. Use the field groupCall.loadedAllParticipants to check whether all participants have already been loaded.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param groupCallId Group call identifier. The group call must be previously received through getGroupCall and must be joined or being joined.
		 * @param limit The maximum number of participants to load; up to 100.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public LoadGroupCallParticipants(int groupCallId, int limit) {
			this.groupCallId = groupCallId;
			this.limit = limit;
		}

		/**
		 * Loads more participants of a group call. The loaded participants will be received through updates. Use the field groupCall.loadedAllParticipants to check whether all participants have already been loaded.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public LoadGroupCallParticipants(DataInput input) throws IOException {
			this.groupCallId = input.readInt();
			this.limit = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return LoadGroupCallParticipants.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(LoadGroupCallParticipants.CONSTRUCTOR);
			output.writeInt(this.groupCallId);
			output.writeInt(this.limit);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			LoadGroupCallParticipants loadGroupCallParticipants = (LoadGroupCallParticipants) o;
			if (this.groupCallId != loadGroupCallParticipants.groupCallId) {
				return false;
			}
			if (this.limit != loadGroupCallParticipants.limit) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.groupCallId);
			return result;
		}
	}

	/**
	 * Closes the TDLib instance after a proper logout. Requires an
	 * available network connection. All local data will be destroyed. After
	 * the logout completes, updateAuthorizationState with
	 * authorizationStateClosed will be sent.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class LogOut extends Function<Ok> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1581923301;

		/**
		 * Closes the TDLib instance after a proper logout. Requires an available network connection. All local data will be destroyed. After the logout completes, updateAuthorizationState with authorizationStateClosed will be sent.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public LogOut() {}

		/**
		 * Closes the TDLib instance after a proper logout. Requires an available network connection. All local data will be destroyed. After the logout completes, updateAuthorizationState with authorizationStateClosed will be sent.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/

		/**
		 * Closes the TDLib instance after a proper logout. Requires an available network connection. All local data will be destroyed. After the logout completes, updateAuthorizationState with authorizationStateClosed will be sent.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public LogOut(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return LogOut.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(LogOut.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return LogOut.CONSTRUCTOR;
		}
	}

	/**
	 * Informs TDLib that the chat is opened by the user. Many useful
	 * activities depend on the chat being opened or closed (e.g., in
	 * supergroups and channels all updates are received only for opened
	 * chats).
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class OpenChat extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -323371509;

		/**
		 * Informs TDLib that the chat is opened by the user. Many useful activities depend on the chat being opened or closed (e.g., in supergroups and channels all updates are received only for opened chats).
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public OpenChat() {}

		/**
		 * Informs TDLib that the chat is opened by the user. Many useful activities depend on the chat being opened or closed (e.g., in supergroups and channels all updates are received only for opened chats).
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public OpenChat(long chatId) {
			this.chatId = chatId;
		}

		/**
		 * Informs TDLib that the chat is opened by the user. Many useful activities depend on the chat being opened or closed (e.g., in supergroups and channels all updates are received only for opened chats).
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public OpenChat(DataInput input) throws IOException {
			this.chatId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return OpenChat.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(OpenChat.CONSTRUCTOR);
			output.writeLong(this.chatId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			OpenChat openChat = (OpenChat) o;
			if (this.chatId != openChat.chatId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.chatId);
		}
	}

	/**
	 * Informs TDLib that the message content has been opened (e.g., the
	 * user has opened a photo, video, document, location or venue, or has
	 * listened to an audio file or voice note message). An
	 * updateMessageContentOpened update will be generated if something has
	 * changed.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class OpenMessageContent extends Function<Ok> {


		/**
		 * Chat identifier of the message.
		**/
		public long chatId;

		/**
		 * Identifier of the message with the opened content.
		**/
		public long messageId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -739088005;

		/**
		 * Informs TDLib that the message content has been opened (e.g., the user has opened a photo, video, document, location or venue, or has listened to an audio file or voice note message). An updateMessageContentOpened update will be generated if something has changed.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public OpenMessageContent() {}

		/**
		 * Informs TDLib that the message content has been opened (e.g., the user has opened a photo, video, document, location or venue, or has listened to an audio file or voice note message). An updateMessageContentOpened update will be generated if something has changed.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier of the message.
		 * @param messageId Identifier of the message with the opened content.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public OpenMessageContent(long chatId, long messageId) {
			this.chatId = chatId;
			this.messageId = messageId;
		}

		/**
		 * Informs TDLib that the message content has been opened (e.g., the user has opened a photo, video, document, location or venue, or has listened to an audio file or voice note message). An updateMessageContentOpened update will be generated if something has changed.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public OpenMessageContent(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return OpenMessageContent.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(OpenMessageContent.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			OpenMessageContent openMessageContent = (OpenMessageContent) o;
			if (this.chatId != openMessageContent.chatId) {
				return false;
			}
			if (this.messageId != openMessageContent.messageId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Informs TDLib that a Web App is being opened from attachment menu, a
	 * botMenuButton button, an internalLinkTypeAttachmentMenuBot link, or
	 * an inlineKeyboardButtonTypeWebApp button. For each bot, a
	 * confirmation alert about data sent to the bot must be shown once.
	 * <p> Returns {@link WebAppInfo WebAppInfo} </p>
	**/
	public static final class OpenWebApp extends Function<WebAppInfo> {


		/**
		 * Identifier of the chat in which the Web App is opened. The Web App can&#039;t be opened in secret chats.
		**/
		public long chatId;

		/**
		 * Identifier of the bot, providing the Web App.
		**/
		public long botUserId;

		/**
		 * The URL from an inlineKeyboardButtonTypeWebApp button, a botMenuButton button, or an internalLinkTypeAttachmentMenuBot link, or an empty string otherwise.
		**/
		public String url;

		/**
		 * Preferred Web App theme; pass null to use the default theme.
		**/
		public ThemeParameters theme;

		/**
		 * Short name of the application; 0-64 English letters, digits, and underscores.
		**/
		public String applicationName;

		/**
		 * If not 0, a message thread identifier in which the message will be sent.
		**/
		public long messageThreadId;

		/**
		 * Identifier of the replied message for the message sent by the Web App; 0 if none.
		**/
		public long replyToMessageId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -763742925;

		/**
		 * Informs TDLib that a Web App is being opened from attachment menu, a botMenuButton button, an internalLinkTypeAttachmentMenuBot link, or an inlineKeyboardButtonTypeWebApp button. For each bot, a confirmation alert about data sent to the bot must be shown once.
		 *
		 * <p> Returns {@link WebAppInfo WebAppInfo} </p>
		**/
		public OpenWebApp() {}

		/**
		 * Informs TDLib that a Web App is being opened from attachment menu, a botMenuButton button, an internalLinkTypeAttachmentMenuBot link, or an inlineKeyboardButtonTypeWebApp button. For each bot, a confirmation alert about data sent to the bot must be shown once.
		 *
		 * <p> Returns {@link WebAppInfo WebAppInfo} </p>
		 *
		 * @param chatId Identifier of the chat in which the Web App is opened. The Web App can&#039;t be opened in secret chats.
		 * @param botUserId Identifier of the bot, providing the Web App.
		 * @param url The URL from an inlineKeyboardButtonTypeWebApp button, a botMenuButton button, or an internalLinkTypeAttachmentMenuBot link, or an empty string otherwise.
		 * @param theme Preferred Web App theme; pass null to use the default theme.
		 * @param applicationName Short name of the application; 0-64 English letters, digits, and underscores.
		 * @param messageThreadId If not 0, a message thread identifier in which the message will be sent.
		 * @param replyToMessageId Identifier of the replied message for the message sent by the Web App; 0 if none.
		 *
		 * <p> Returns {@link WebAppInfo WebAppInfo} </p>
		**/
		public OpenWebApp(long chatId,
				long botUserId,
				String url,
				ThemeParameters theme,
				String applicationName,
				long messageThreadId,
				long replyToMessageId) {
			this.chatId = chatId;
			this.botUserId = botUserId;
			this.url = url;
			this.theme = theme;
			this.applicationName = applicationName;
			this.messageThreadId = messageThreadId;
			this.replyToMessageId = replyToMessageId;
		}

		/**
		 * Informs TDLib that a Web App is being opened from attachment menu, a botMenuButton button, an internalLinkTypeAttachmentMenuBot link, or an inlineKeyboardButtonTypeWebApp button. For each bot, a confirmation alert about data sent to the bot must be shown once.
		 *
		 * <p> Returns {@link WebAppInfo WebAppInfo} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public OpenWebApp(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.botUserId = input.readLong();
			if (input.readBoolean()) {
				byte[] urlTmp = new byte[input.readInt()];
				input.readFully(urlTmp);
				this.url = new String(urlTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (ThemeParameters.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.theme = new ThemeParameters(input);
			}
			if (input.readBoolean()) {
				byte[] applicationNameTmp = new byte[input.readInt()];
				input.readFully(applicationNameTmp);
				this.applicationName = new String(applicationNameTmp, StandardCharsets.UTF_8);
			}
			this.messageThreadId = input.readLong();
			this.replyToMessageId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return OpenWebApp.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(OpenWebApp.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.botUserId);
			if (this.url == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] urlTmp = this.url.getBytes(StandardCharsets.UTF_8);
				output.writeInt(urlTmp.length);
				output.write(urlTmp);
			}
			if (this.theme == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.theme.serialize(output);
			}
			if (this.applicationName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] applicationNameTmp = this.applicationName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(applicationNameTmp.length);
				output.write(applicationNameTmp);
			}
			output.writeLong(this.messageThreadId);
			output.writeLong(this.replyToMessageId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			OpenWebApp openWebApp = (OpenWebApp) o;
			if (this.chatId != openWebApp.chatId) {
				return false;
			}
			if (this.botUserId != openWebApp.botUserId) {
				return false;
			}
			if (this.url != openWebApp.url) {
				return false;
			}
			if (!Objects.equals(this.theme, openWebApp.theme)) {
				return false;
			}
			if (this.applicationName != openWebApp.applicationName) {
				return false;
			}
			if (this.messageThreadId != openWebApp.messageThreadId) {
				return false;
			}
			if (this.replyToMessageId != openWebApp.replyToMessageId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.url == null ? 0 : this.url.hashCode());
			result = result * 31 + (this.theme == null ? 0 : this.theme.hashCode());
			result = result * 31 + (this.applicationName == null ? 0 : this.applicationName.hashCode());
			return result;
		}
	}

	/**
	 * Optimizes storage usage, i.e. deletes some files and returns new
	 * storage usage statistics. Secret thumbnails can&#039;t be deleted.
	 * <p> Returns {@link StorageStatistics StorageStatistics} </p>
	**/
	public static final class OptimizeStorage extends Function<StorageStatistics> {


		/**
		 * Limit on the total size of files after deletion, in bytes. Pass -1 to use the default limit.
		**/
		public long size;

		/**
		 * Limit on the time that has passed since the last time a file was accessed (or creation time for some filesystems). Pass -1 to use the default limit.
		**/
		public int ttl;

		/**
		 * Limit on the total number of files after deletion. Pass -1 to use the default limit.
		**/
		public int count;

		/**
		 * The amount of time after the creation of a file during which it can&#039;t be deleted, in seconds. Pass -1 to use the default value.
		**/
		public int immunityDelay;

		/**
		 * If non-empty, only files with the given types are considered. By default, all types except thumbnails, profile photos, stickers and wallpapers are deleted.
		**/
		public FileType[] fileTypes;

		/**
		 * If non-empty, only files from the given chats are considered. Use 0 as chat identifier to delete files not belonging to any chat (e.g., profile photos).
		**/
		public long[] chatIds;

		/**
		 * If non-empty, files from the given chats are excluded. Use 0 as chat identifier to exclude all files not belonging to any chat (e.g., profile photos).
		**/
		public long[] excludeChatIds;

		/**
		 * Pass true if statistics about the files that were deleted must be returned instead of the whole storage usage statistics. Affects only returned statistics.
		**/
		public boolean returnDeletedFileStatistics;

		/**
		 * Same as in getStorageStatistics. Affects only returned statistics.
		**/
		public int chatLimit;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 853186759;

		/**
		 * Optimizes storage usage, i.e. deletes some files and returns new storage usage statistics. Secret thumbnails can&#039;t be deleted.
		 *
		 * <p> Returns {@link StorageStatistics StorageStatistics} </p>
		**/
		public OptimizeStorage() {}

		/**
		 * Optimizes storage usage, i.e. deletes some files and returns new storage usage statistics. Secret thumbnails can&#039;t be deleted.
		 *
		 * <p> Returns {@link StorageStatistics StorageStatistics} </p>
		 *
		 * @param size Limit on the total size of files after deletion, in bytes. Pass -1 to use the default limit.
		 * @param ttl Limit on the time that has passed since the last time a file was accessed (or creation time for some filesystems). Pass -1 to use the default limit.
		 * @param count Limit on the total number of files after deletion. Pass -1 to use the default limit.
		 * @param immunityDelay The amount of time after the creation of a file during which it can&#039;t be deleted, in seconds. Pass -1 to use the default value.
		 * @param fileTypes If non-empty, only files with the given types are considered. By default, all types except thumbnails, profile photos, stickers and wallpapers are deleted.
		 * @param chatIds If non-empty, only files from the given chats are considered. Use 0 as chat identifier to delete files not belonging to any chat (e.g., profile photos).
		 * @param excludeChatIds If non-empty, files from the given chats are excluded. Use 0 as chat identifier to exclude all files not belonging to any chat (e.g., profile photos).
		 * @param returnDeletedFileStatistics Pass true if statistics about the files that were deleted must be returned instead of the whole storage usage statistics. Affects only returned statistics.
		 * @param chatLimit Same as in getStorageStatistics. Affects only returned statistics.
		 *
		 * <p> Returns {@link StorageStatistics StorageStatistics} </p>
		**/
		public OptimizeStorage(long size,
				int ttl,
				int count,
				int immunityDelay,
				FileType[] fileTypes,
				long[] chatIds,
				long[] excludeChatIds,
				boolean returnDeletedFileStatistics,
				int chatLimit) {
			this.size = size;
			this.ttl = ttl;
			this.count = count;
			this.immunityDelay = immunityDelay;
			this.fileTypes = fileTypes;
			this.chatIds = chatIds;
			this.excludeChatIds = excludeChatIds;
			this.returnDeletedFileStatistics = returnDeletedFileStatistics;
			this.chatLimit = chatLimit;
		}

		/**
		 * Optimizes storage usage, i.e. deletes some files and returns new storage usage statistics. Secret thumbnails can&#039;t be deleted.
		 *
		 * <p> Returns {@link StorageStatistics StorageStatistics} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public OptimizeStorage(DataInput input) throws IOException {
			this.size = input.readLong();
			this.ttl = input.readInt();
			this.count = input.readInt();
			this.immunityDelay = input.readInt();
			if (input.readBoolean()) {
				this.fileTypes = new FileType[input.readInt()];
				for (int i = 0; i < this.fileTypes.length; i++) {
					switch(input.readInt()) {
						case FileTypeNone.CONSTRUCTOR: this.fileTypes[i] = new FileTypeNone(input); break;
						case FileTypeAnimation.CONSTRUCTOR: this.fileTypes[i] = new FileTypeAnimation(input); break;
						case FileTypeAudio.CONSTRUCTOR: this.fileTypes[i] = new FileTypeAudio(input); break;
						case FileTypeDocument.CONSTRUCTOR: this.fileTypes[i] = new FileTypeDocument(input); break;
						case FileTypeNotificationSound.CONSTRUCTOR: this.fileTypes[i] = new FileTypeNotificationSound(input); break;
						case FileTypePhoto.CONSTRUCTOR: this.fileTypes[i] = new FileTypePhoto(input); break;
						case FileTypeProfilePhoto.CONSTRUCTOR: this.fileTypes[i] = new FileTypeProfilePhoto(input); break;
						case FileTypeSecret.CONSTRUCTOR: this.fileTypes[i] = new FileTypeSecret(input); break;
						case FileTypeSecretThumbnail.CONSTRUCTOR: this.fileTypes[i] = new FileTypeSecretThumbnail(input); break;
						case FileTypeSecure.CONSTRUCTOR: this.fileTypes[i] = new FileTypeSecure(input); break;
						case FileTypeSticker.CONSTRUCTOR: this.fileTypes[i] = new FileTypeSticker(input); break;
						case FileTypeThumbnail.CONSTRUCTOR: this.fileTypes[i] = new FileTypeThumbnail(input); break;
						case FileTypeUnknown.CONSTRUCTOR: this.fileTypes[i] = new FileTypeUnknown(input); break;
						case FileTypeVideo.CONSTRUCTOR: this.fileTypes[i] = new FileTypeVideo(input); break;
						case FileTypeVideoNote.CONSTRUCTOR: this.fileTypes[i] = new FileTypeVideoNote(input); break;
						case FileTypeVoiceNote.CONSTRUCTOR: this.fileTypes[i] = new FileTypeVoiceNote(input); break;
						case FileTypeWallpaper.CONSTRUCTOR: this.fileTypes[i] = new FileTypeWallpaper(input); break;
						default: {
							throw new UnsupportedOperationException();
						}
					}
				}
			}
			if (input.readBoolean()) {
				this.chatIds = new long[input.readInt()];
				for (int i = 0; i < this.chatIds.length; i++) {
					this.chatIds[i] = input.readLong();
				}
			}
			if (input.readBoolean()) {
				this.excludeChatIds = new long[input.readInt()];
				for (int i = 0; i < this.excludeChatIds.length; i++) {
					this.excludeChatIds[i] = input.readLong();
				}
			}
			this.returnDeletedFileStatistics = input.readBoolean();
			this.chatLimit = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return OptimizeStorage.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(OptimizeStorage.CONSTRUCTOR);
			output.writeLong(this.size);
			output.writeInt(this.ttl);
			output.writeInt(this.count);
			output.writeInt(this.immunityDelay);
			if (this.fileTypes == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.fileTypes.length);
				for (int i = 0; i < this.fileTypes.length; i++) {
					this.fileTypes[i].serialize(output);
				}
			}
			if (this.chatIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.chatIds.length);
				for (int i = 0; i < this.chatIds.length; i++) {
					output.writeLong(this.chatIds[i]);
				}
			}
			if (this.excludeChatIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.excludeChatIds.length);
				for (int i = 0; i < this.excludeChatIds.length; i++) {
					output.writeLong(this.excludeChatIds[i]);
				}
			}
			output.writeBoolean(this.returnDeletedFileStatistics);
			output.writeInt(this.chatLimit);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			OptimizeStorage optimizeStorage = (OptimizeStorage) o;
			if (this.size != optimizeStorage.size) {
				return false;
			}
			if (this.ttl != optimizeStorage.ttl) {
				return false;
			}
			if (this.count != optimizeStorage.count) {
				return false;
			}
			if (this.immunityDelay != optimizeStorage.immunityDelay) {
				return false;
			}
			if (!Arrays.equals(this.fileTypes, optimizeStorage.fileTypes)) {
				return false;
			}
			if (!Arrays.equals(this.chatIds, optimizeStorage.chatIds)) {
				return false;
			}
			if (!Arrays.equals(this.excludeChatIds, optimizeStorage.excludeChatIds)) {
				return false;
			}
			if (this.returnDeletedFileStatistics != optimizeStorage.returnDeletedFileStatistics) {
				return false;
			}
			if (this.chatLimit != optimizeStorage.chatLimit) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.size);
			result = result * 31 + (Arrays.hashCode(this.fileTypes));
			result = result * 31 + (Arrays.hashCode(this.chatIds));
			result = result * 31 + (Arrays.hashCode(this.excludeChatIds));
			return result;
		}
	}

	/**
	 * Parses Markdown entities in a human-friendly format, ignoring markup
	 * errors. Can be called synchronously.
	 * <p> Returns {@link FormattedText FormattedText} </p>
	**/
	public static final class ParseMarkdown extends Function<FormattedText> {


		/**
		 * The text to parse. For example, &quot;__italic__ ~~strikethrough~~ ||spoiler|| **bold** `code` ```pre``` __[italic__ textUrl](telegram.org) _Italic**bold italic_Bold**&quot;.
		**/
		public FormattedText text;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 756366063;

		/**
		 * Parses Markdown entities in a human-friendly format, ignoring markup errors. Can be called synchronously.
		 *
		 * <p> Returns {@link FormattedText FormattedText} </p>
		**/
		public ParseMarkdown() {}

		/**
		 * Parses Markdown entities in a human-friendly format, ignoring markup errors. Can be called synchronously.
		 *
		 * <p> Returns {@link FormattedText FormattedText} </p>
		 *
		 * @param text The text to parse. For example, &quot;__italic__ ~~strikethrough~~ ||spoiler|| **bold** `code` ```pre``` __[italic__ textUrl](telegram.org) _Italic**bold italic_Bold**&quot;.
		 *
		 * <p> Returns {@link FormattedText FormattedText} </p>
		**/
		public ParseMarkdown(FormattedText text) {
			this.text = text;
		}

		/**
		 * Parses Markdown entities in a human-friendly format, ignoring markup errors. Can be called synchronously.
		 *
		 * <p> Returns {@link FormattedText FormattedText} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ParseMarkdown(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (FormattedText.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.text = new FormattedText(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ParseMarkdown.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ParseMarkdown.CONSTRUCTOR);
			if (this.text == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.text.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ParseMarkdown parseMarkdown = (ParseMarkdown) o;
			if (!Objects.equals(this.text, parseMarkdown.text)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.text == null ? 0 : this.text.hashCode();
		}
	}

	/**
	 * Parses Bold, Italic, Underline, Strikethrough, Spoiler, CustomEmoji,
	 * Code, Pre, PreCode, TextUrl and MentionName entities from a marked-up
	 * text. Can be called synchronously.
	 * <p> Returns {@link FormattedText FormattedText} </p>
	**/
	public static final class ParseTextEntities extends Function<FormattedText> {


		/**
		 * The text to parse.
		**/
		public String text;

		/**
		 * Text parse mode.
		**/
		public TextParseMode parseMode;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1709194593;

		/**
		 * Parses Bold, Italic, Underline, Strikethrough, Spoiler, CustomEmoji, Code, Pre, PreCode, TextUrl and MentionName entities from a marked-up text. Can be called synchronously.
		 *
		 * <p> Returns {@link FormattedText FormattedText} </p>
		**/
		public ParseTextEntities() {}

		/**
		 * Parses Bold, Italic, Underline, Strikethrough, Spoiler, CustomEmoji, Code, Pre, PreCode, TextUrl and MentionName entities from a marked-up text. Can be called synchronously.
		 *
		 * <p> Returns {@link FormattedText FormattedText} </p>
		 *
		 * @param text The text to parse.
		 * @param parseMode Text parse mode.
		 *
		 * <p> Returns {@link FormattedText FormattedText} </p>
		**/
		public ParseTextEntities(String text, TextParseMode parseMode) {
			this.text = text;
			this.parseMode = parseMode;
		}

		/**
		 * Parses Bold, Italic, Underline, Strikethrough, Spoiler, CustomEmoji, Code, Pre, PreCode, TextUrl and MentionName entities from a marked-up text. Can be called synchronously.
		 *
		 * <p> Returns {@link FormattedText FormattedText} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ParseTextEntities(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] textTmp = new byte[input.readInt()];
				input.readFully(textTmp);
				this.text = new String(textTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case TextParseModeMarkdown.CONSTRUCTOR: this.parseMode = new TextParseModeMarkdown(input); break;
					case TextParseModeHTML.CONSTRUCTOR: this.parseMode = new TextParseModeHTML(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ParseTextEntities.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ParseTextEntities.CONSTRUCTOR);
			if (this.text == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] textTmp = this.text.getBytes(StandardCharsets.UTF_8);
				output.writeInt(textTmp.length);
				output.write(textTmp);
			}
			if (this.parseMode == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.parseMode.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ParseTextEntities parseTextEntities = (ParseTextEntities) o;
			if (this.text != parseTextEntities.text) {
				return false;
			}
			if (!Objects.equals(this.parseMode, parseTextEntities.parseMode)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.text == null ? 0 : this.text.hashCode();
			result = result * 31 + (this.parseMode == null ? 0 : this.parseMode.hashCode());
			return result;
		}
	}

	/**
	 * Pins a message in a chat; requires canPinMessages rights or
	 * canEditMessages rights in the channel.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class PinChatMessage extends Function<Ok> {


		/**
		 * Identifier of the chat.
		**/
		public long chatId;

		/**
		 * Identifier of the new pinned message.
		**/
		public long messageId;

		/**
		 * Pass true to disable notification about the pinned message. Notifications are always disabled in channels and private chats.
		**/
		public boolean disableNotification;

		/**
		 * Pass true to pin the message only for self; private chats only.
		**/
		public boolean onlyForSelf;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2034719663;

		/**
		 * Pins a message in a chat; requires canPinMessages rights or canEditMessages rights in the channel.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public PinChatMessage() {}

		/**
		 * Pins a message in a chat; requires canPinMessages rights or canEditMessages rights in the channel.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Identifier of the chat.
		 * @param messageId Identifier of the new pinned message.
		 * @param disableNotification Pass true to disable notification about the pinned message. Notifications are always disabled in channels and private chats.
		 * @param onlyForSelf Pass true to pin the message only for self; private chats only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public PinChatMessage(long chatId,
				long messageId,
				boolean disableNotification,
				boolean onlyForSelf) {
			this.chatId = chatId;
			this.messageId = messageId;
			this.disableNotification = disableNotification;
			this.onlyForSelf = onlyForSelf;
		}

		/**
		 * Pins a message in a chat; requires canPinMessages rights or canEditMessages rights in the channel.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PinChatMessage(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
			this.disableNotification = input.readBoolean();
			this.onlyForSelf = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PinChatMessage.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PinChatMessage.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
			output.writeBoolean(this.disableNotification);
			output.writeBoolean(this.onlyForSelf);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PinChatMessage pinChatMessage = (PinChatMessage) o;
			if (this.chatId != pinChatMessage.chatId) {
				return false;
			}
			if (this.messageId != pinChatMessage.messageId) {
				return false;
			}
			if (this.disableNotification != pinChatMessage.disableNotification) {
				return false;
			}
			if (this.onlyForSelf != pinChatMessage.onlyForSelf) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Computes time needed to receive a response from a Telegram server
	 * through a proxy. Can be called before authorization.
	 * <p> Returns {@link Seconds Seconds} </p>
	**/
	public static final class PingProxy extends Function<Seconds> {


		/**
		 * Proxy identifier. Use 0 to ping a Telegram server without a proxy.
		**/
		public int proxyId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -979681103;

		/**
		 * Computes time needed to receive a response from a Telegram server through a proxy. Can be called before authorization.
		 *
		 * <p> Returns {@link Seconds Seconds} </p>
		**/
		public PingProxy() {}

		/**
		 * Computes time needed to receive a response from a Telegram server through a proxy. Can be called before authorization.
		 *
		 * <p> Returns {@link Seconds Seconds} </p>
		 *
		 * @param proxyId Proxy identifier. Use 0 to ping a Telegram server without a proxy.
		 *
		 * <p> Returns {@link Seconds Seconds} </p>
		**/
		public PingProxy(int proxyId) {
			this.proxyId = proxyId;
		}

		/**
		 * Computes time needed to receive a response from a Telegram server through a proxy. Can be called before authorization.
		 *
		 * <p> Returns {@link Seconds Seconds} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PingProxy(DataInput input) throws IOException {
			this.proxyId = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PingProxy.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PingProxy.CONSTRUCTOR);
			output.writeInt(this.proxyId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PingProxy pingProxy = (PingProxy) o;
			if (this.proxyId != pingProxy.proxyId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.proxyId);
		}
	}

	/**
	 * Preliminary uploads a file to the cloud before sending it in a
	 * message, which can be useful for uploading of being recorded voice
	 * and video notes. Updates updateFile will be used to notify about
	 * upload progress and successful completion of the upload. The file
	 * will not have a persistent remote identifier until it will be sent in
	 * a message.
	 * <p> Returns {@link File File} </p>
	**/
	public static final class PreliminaryUploadFile extends Function<File> {


		/**
		 * File to upload.
		**/
		public InputFile file;

		/**
		 * File type; pass null if unknown.
		**/
		public FileType fileType;

		/**
		 * Priority of the upload (1-32). The higher the priority, the earlier the file will be uploaded. If the priorities of two files are equal, then the first one for which preliminaryUploadFile was called will be uploaded first.
		**/
		public int priority;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1894239129;

		/**
		 * Preliminary uploads a file to the cloud before sending it in a message, which can be useful for uploading of being recorded voice and video notes. Updates updateFile will be used to notify about upload progress and successful completion of the upload. The file will not have a persistent remote identifier until it will be sent in a message.
		 *
		 * <p> Returns {@link File File} </p>
		**/
		public PreliminaryUploadFile() {}

		/**
		 * Preliminary uploads a file to the cloud before sending it in a message, which can be useful for uploading of being recorded voice and video notes. Updates updateFile will be used to notify about upload progress and successful completion of the upload. The file will not have a persistent remote identifier until it will be sent in a message.
		 *
		 * <p> Returns {@link File File} </p>
		 *
		 * @param file File to upload.
		 * @param fileType File type; pass null if unknown.
		 * @param priority Priority of the upload (1-32). The higher the priority, the earlier the file will be uploaded. If the priorities of two files are equal, then the first one for which preliminaryUploadFile was called will be uploaded first.
		 *
		 * <p> Returns {@link File File} </p>
		**/
		public PreliminaryUploadFile(InputFile file, FileType fileType, int priority) {
			this.file = file;
			this.fileType = fileType;
			this.priority = priority;
		}

		/**
		 * Preliminary uploads a file to the cloud before sending it in a message, which can be useful for uploading of being recorded voice and video notes. Updates updateFile will be used to notify about upload progress and successful completion of the upload. The file will not have a persistent remote identifier until it will be sent in a message.
		 *
		 * <p> Returns {@link File File} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public PreliminaryUploadFile(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputFileId.CONSTRUCTOR: this.file = new InputFileId(input); break;
					case InputFileRemote.CONSTRUCTOR: this.file = new InputFileRemote(input); break;
					case InputFileLocal.CONSTRUCTOR: this.file = new InputFileLocal(input); break;
					case InputFileGenerated.CONSTRUCTOR: this.file = new InputFileGenerated(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case FileTypeNone.CONSTRUCTOR: this.fileType = new FileTypeNone(input); break;
					case FileTypeAnimation.CONSTRUCTOR: this.fileType = new FileTypeAnimation(input); break;
					case FileTypeAudio.CONSTRUCTOR: this.fileType = new FileTypeAudio(input); break;
					case FileTypeDocument.CONSTRUCTOR: this.fileType = new FileTypeDocument(input); break;
					case FileTypeNotificationSound.CONSTRUCTOR: this.fileType = new FileTypeNotificationSound(input); break;
					case FileTypePhoto.CONSTRUCTOR: this.fileType = new FileTypePhoto(input); break;
					case FileTypeProfilePhoto.CONSTRUCTOR: this.fileType = new FileTypeProfilePhoto(input); break;
					case FileTypeSecret.CONSTRUCTOR: this.fileType = new FileTypeSecret(input); break;
					case FileTypeSecretThumbnail.CONSTRUCTOR: this.fileType = new FileTypeSecretThumbnail(input); break;
					case FileTypeSecure.CONSTRUCTOR: this.fileType = new FileTypeSecure(input); break;
					case FileTypeSticker.CONSTRUCTOR: this.fileType = new FileTypeSticker(input); break;
					case FileTypeThumbnail.CONSTRUCTOR: this.fileType = new FileTypeThumbnail(input); break;
					case FileTypeUnknown.CONSTRUCTOR: this.fileType = new FileTypeUnknown(input); break;
					case FileTypeVideo.CONSTRUCTOR: this.fileType = new FileTypeVideo(input); break;
					case FileTypeVideoNote.CONSTRUCTOR: this.fileType = new FileTypeVideoNote(input); break;
					case FileTypeVoiceNote.CONSTRUCTOR: this.fileType = new FileTypeVoiceNote(input); break;
					case FileTypeWallpaper.CONSTRUCTOR: this.fileType = new FileTypeWallpaper(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.priority = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return PreliminaryUploadFile.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(PreliminaryUploadFile.CONSTRUCTOR);
			if (this.file == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.file.serialize(output);
			}
			if (this.fileType == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.fileType.serialize(output);
			}
			output.writeInt(this.priority);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			PreliminaryUploadFile preliminaryUploadFile = (PreliminaryUploadFile) o;
			if (!Objects.equals(this.file, preliminaryUploadFile.file)) {
				return false;
			}
			if (!Objects.equals(this.fileType, preliminaryUploadFile.fileType)) {
				return false;
			}
			if (this.priority != preliminaryUploadFile.priority) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.priority);
			result = result * 31 + (this.file == null ? 0 : this.file.hashCode());
			result = result * 31 + (this.fileType == null ? 0 : this.fileType.hashCode());
			return result;
		}
	}

	/**
	 * Process new chats added to a shareable chat folder by its owner.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ProcessChatFolderNewChats extends Function<Ok> {


		/**
		 * Chat folder identifier.
		**/
		public int chatFolderId;

		/**
		 * Identifiers of the new chats, which are added to the chat folder. The chats are automatically joined if they aren&#039;t joined yet.
		**/
		public long[] addedChatIds;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1498280672;

		/**
		 * Process new chats added to a shareable chat folder by its owner.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ProcessChatFolderNewChats() {}

		/**
		 * Process new chats added to a shareable chat folder by its owner.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatFolderId Chat folder identifier.
		 * @param addedChatIds Identifiers of the new chats, which are added to the chat folder. The chats are automatically joined if they aren&#039;t joined yet.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ProcessChatFolderNewChats(int chatFolderId, long[] addedChatIds) {
			this.chatFolderId = chatFolderId;
			this.addedChatIds = addedChatIds;
		}

		/**
		 * Process new chats added to a shareable chat folder by its owner.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ProcessChatFolderNewChats(DataInput input) throws IOException {
			this.chatFolderId = input.readInt();
			if (input.readBoolean()) {
				this.addedChatIds = new long[input.readInt()];
				for (int i = 0; i < this.addedChatIds.length; i++) {
					this.addedChatIds[i] = input.readLong();
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ProcessChatFolderNewChats.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ProcessChatFolderNewChats.CONSTRUCTOR);
			output.writeInt(this.chatFolderId);
			if (this.addedChatIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.addedChatIds.length);
				for (int i = 0; i < this.addedChatIds.length; i++) {
					output.writeLong(this.addedChatIds[i]);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ProcessChatFolderNewChats processChatFolderNewChats = (ProcessChatFolderNewChats) o;
			if (this.chatFolderId != processChatFolderNewChats.chatFolderId) {
				return false;
			}
			if (!Arrays.equals(this.addedChatIds, processChatFolderNewChats.addedChatIds)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.chatFolderId);
			result = result * 31 + (Arrays.hashCode(this.addedChatIds));
			return result;
		}
	}

	/**
	 * Handles a pending join request in a chat.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ProcessChatJoinRequest extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Identifier of the user that sent the request.
		**/
		public long userId;

		/**
		 * Pass true to approve the request; pass false to decline it.
		**/
		public boolean approve;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1004876963;

		/**
		 * Handles a pending join request in a chat.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ProcessChatJoinRequest() {}

		/**
		 * Handles a pending join request in a chat.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param userId Identifier of the user that sent the request.
		 * @param approve Pass true to approve the request; pass false to decline it.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ProcessChatJoinRequest(long chatId, long userId, boolean approve) {
			this.chatId = chatId;
			this.userId = userId;
			this.approve = approve;
		}

		/**
		 * Handles a pending join request in a chat.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ProcessChatJoinRequest(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.userId = input.readLong();
			this.approve = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ProcessChatJoinRequest.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ProcessChatJoinRequest.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.userId);
			output.writeBoolean(this.approve);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ProcessChatJoinRequest processChatJoinRequest = (ProcessChatJoinRequest) o;
			if (this.chatId != processChatJoinRequest.chatId) {
				return false;
			}
			if (this.userId != processChatJoinRequest.userId) {
				return false;
			}
			if (this.approve != processChatJoinRequest.approve) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Handles all pending join requests for a given link in a chat.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ProcessChatJoinRequests extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Invite link for which to process join requests. If empty, all join requests will be processed. Requires administrator privileges and canInviteUsers right in the chat for own links and owner privileges for other links.
		**/
		public String inviteLink;

		/**
		 * Pass true to approve all requests; pass false to decline them.
		**/
		public boolean approve;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1048722894;

		/**
		 * Handles all pending join requests for a given link in a chat.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ProcessChatJoinRequests() {}

		/**
		 * Handles all pending join requests for a given link in a chat.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param inviteLink Invite link for which to process join requests. If empty, all join requests will be processed. Requires administrator privileges and canInviteUsers right in the chat for own links and owner privileges for other links.
		 * @param approve Pass true to approve all requests; pass false to decline them.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ProcessChatJoinRequests(long chatId, String inviteLink, boolean approve) {
			this.chatId = chatId;
			this.inviteLink = inviteLink;
			this.approve = approve;
		}

		/**
		 * Handles all pending join requests for a given link in a chat.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ProcessChatJoinRequests(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				byte[] inviteLinkTmp = new byte[input.readInt()];
				input.readFully(inviteLinkTmp);
				this.inviteLink = new String(inviteLinkTmp, StandardCharsets.UTF_8);
			}
			this.approve = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ProcessChatJoinRequests.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ProcessChatJoinRequests.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.inviteLink == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] inviteLinkTmp = this.inviteLink.getBytes(StandardCharsets.UTF_8);
				output.writeInt(inviteLinkTmp.length);
				output.write(inviteLinkTmp);
			}
			output.writeBoolean(this.approve);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ProcessChatJoinRequests processChatJoinRequests = (ProcessChatJoinRequests) o;
			if (this.chatId != processChatJoinRequests.chatId) {
				return false;
			}
			if (this.inviteLink != processChatJoinRequests.inviteLink) {
				return false;
			}
			if (this.approve != processChatJoinRequests.approve) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.inviteLink == null ? 0 : this.inviteLink.hashCode());
			return result;
		}
	}

	/**
	 * Handles a push notification. Returns error with code 406 if the push
	 * notification is not supported and connection to the server is
	 * required to fetch new data. Can be called before authorization.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ProcessPushNotification extends Function<Ok> {


		/**
		 * JSON-encoded push notification payload with all fields sent by the server, and &quot;google.sentTime&quot; and &quot;google.notification.sound&quot; fields added.
		**/
		public String payload;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 786679952;

		/**
		 * Handles a push notification. Returns error with code 406 if the push notification is not supported and connection to the server is required to fetch new data. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ProcessPushNotification() {}

		/**
		 * Handles a push notification. Returns error with code 406 if the push notification is not supported and connection to the server is required to fetch new data. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param payload JSON-encoded push notification payload with all fields sent by the server, and &quot;google.sentTime&quot; and &quot;google.notification.sound&quot; fields added.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ProcessPushNotification(String payload) {
			this.payload = payload;
		}

		/**
		 * Handles a push notification. Returns error with code 406 if the push notification is not supported and connection to the server is required to fetch new data. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ProcessPushNotification(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] payloadTmp = new byte[input.readInt()];
				input.readFully(payloadTmp);
				this.payload = new String(payloadTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ProcessPushNotification.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ProcessPushNotification.CONSTRUCTOR);
			if (this.payload == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] payloadTmp = this.payload.getBytes(StandardCharsets.UTF_8);
				output.writeInt(payloadTmp.length);
				output.write(payloadTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ProcessPushNotification processPushNotification = (ProcessPushNotification) o;
			if (this.payload != processPushNotification.payload) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.payload == null ? 0 : this.payload.hashCode();
		}
	}

	/**
	 * Rates recognized speech in a video note or a voice note message.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class RateSpeechRecognition extends Function<Ok> {


		/**
		 * Identifier of the chat to which the message belongs.
		**/
		public long chatId;

		/**
		 * Identifier of the message.
		**/
		public long messageId;

		/**
		 * Pass true if the speech recognition is good.
		**/
		public boolean isGood;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -287521867;

		/**
		 * Rates recognized speech in a video note or a voice note message.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public RateSpeechRecognition() {}

		/**
		 * Rates recognized speech in a video note or a voice note message.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Identifier of the chat to which the message belongs.
		 * @param messageId Identifier of the message.
		 * @param isGood Pass true if the speech recognition is good.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public RateSpeechRecognition(long chatId, long messageId, boolean isGood) {
			this.chatId = chatId;
			this.messageId = messageId;
			this.isGood = isGood;
		}

		/**
		 * Rates recognized speech in a video note or a voice note message.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RateSpeechRecognition(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
			this.isGood = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RateSpeechRecognition.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RateSpeechRecognition.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
			output.writeBoolean(this.isGood);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			RateSpeechRecognition rateSpeechRecognition = (RateSpeechRecognition) o;
			if (this.chatId != rateSpeechRecognition.chatId) {
				return false;
			}
			if (this.messageId != rateSpeechRecognition.messageId) {
				return false;
			}
			if (this.isGood != rateSpeechRecognition.isGood) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Marks all mentions in a chat as read.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ReadAllChatMentions extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1357558453;

		/**
		 * Marks all mentions in a chat as read.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ReadAllChatMentions() {}

		/**
		 * Marks all mentions in a chat as read.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ReadAllChatMentions(long chatId) {
			this.chatId = chatId;
		}

		/**
		 * Marks all mentions in a chat as read.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ReadAllChatMentions(DataInput input) throws IOException {
			this.chatId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ReadAllChatMentions.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ReadAllChatMentions.CONSTRUCTOR);
			output.writeLong(this.chatId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ReadAllChatMentions readAllChatMentions = (ReadAllChatMentions) o;
			if (this.chatId != readAllChatMentions.chatId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.chatId);
		}
	}

	/**
	 * Marks all reactions in a chat or a forum topic as read.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ReadAllChatReactions extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1421973357;

		/**
		 * Marks all reactions in a chat or a forum topic as read.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ReadAllChatReactions() {}

		/**
		 * Marks all reactions in a chat or a forum topic as read.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ReadAllChatReactions(long chatId) {
			this.chatId = chatId;
		}

		/**
		 * Marks all reactions in a chat or a forum topic as read.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ReadAllChatReactions(DataInput input) throws IOException {
			this.chatId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ReadAllChatReactions.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ReadAllChatReactions.CONSTRUCTOR);
			output.writeLong(this.chatId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ReadAllChatReactions readAllChatReactions = (ReadAllChatReactions) o;
			if (this.chatId != readAllChatReactions.chatId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.chatId);
		}
	}

	/**
	 * Marks all mentions in a forum topic as read.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ReadAllMessageThreadMentions extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Message thread identifier in which mentions are marked as read.
		**/
		public long messageThreadId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1323136341;

		/**
		 * Marks all mentions in a forum topic as read.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ReadAllMessageThreadMentions() {}

		/**
		 * Marks all mentions in a forum topic as read.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param messageThreadId Message thread identifier in which mentions are marked as read.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ReadAllMessageThreadMentions(long chatId, long messageThreadId) {
			this.chatId = chatId;
			this.messageThreadId = messageThreadId;
		}

		/**
		 * Marks all mentions in a forum topic as read.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ReadAllMessageThreadMentions(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageThreadId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ReadAllMessageThreadMentions.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ReadAllMessageThreadMentions.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageThreadId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ReadAllMessageThreadMentions readAllMessageThreadMentions = (ReadAllMessageThreadMentions) o;
			if (this.chatId != readAllMessageThreadMentions.chatId) {
				return false;
			}
			if (this.messageThreadId != readAllMessageThreadMentions.messageThreadId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Marks all reactions in a forum topic as read.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ReadAllMessageThreadReactions extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Message thread identifier in which reactions are marked as read.
		**/
		public long messageThreadId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -792975554;

		/**
		 * Marks all reactions in a forum topic as read.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ReadAllMessageThreadReactions() {}

		/**
		 * Marks all reactions in a forum topic as read.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param messageThreadId Message thread identifier in which reactions are marked as read.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ReadAllMessageThreadReactions(long chatId, long messageThreadId) {
			this.chatId = chatId;
			this.messageThreadId = messageThreadId;
		}

		/**
		 * Marks all reactions in a forum topic as read.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ReadAllMessageThreadReactions(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageThreadId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ReadAllMessageThreadReactions.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ReadAllMessageThreadReactions.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageThreadId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ReadAllMessageThreadReactions readAllMessageThreadReactions = (ReadAllMessageThreadReactions) o;
			if (this.chatId != readAllMessageThreadReactions.chatId) {
				return false;
			}
			if (this.messageThreadId != readAllMessageThreadReactions.messageThreadId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Traverse all chats in a chat list and marks all messages in the chats
	 * as read.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ReadChatList extends Function<Ok> {


		/**
		 * Chat list in which to mark all chats as read.
		**/
		public ChatList chatList;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1117480790;

		/**
		 * Traverse all chats in a chat list and marks all messages in the chats as read.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ReadChatList() {}

		/**
		 * Traverse all chats in a chat list and marks all messages in the chats as read.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatList Chat list in which to mark all chats as read.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ReadChatList(ChatList chatList) {
			this.chatList = chatList;
		}

		/**
		 * Traverse all chats in a chat list and marks all messages in the chats as read.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ReadChatList(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ChatListMain.CONSTRUCTOR: this.chatList = new ChatListMain(input); break;
					case ChatListArchive.CONSTRUCTOR: this.chatList = new ChatListArchive(input); break;
					case ChatListFolder.CONSTRUCTOR: this.chatList = new ChatListFolder(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ReadChatList.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ReadChatList.CONSTRUCTOR);
			if (this.chatList == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.chatList.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ReadChatList readChatList = (ReadChatList) o;
			if (!Objects.equals(this.chatList, readChatList.chatList)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.chatList == null ? 0 : this.chatList.hashCode();
		}
	}

	/**
	 * Reads a part of a file from the TDLib file cache and returns read
	 * bytes. This method is intended to be used only if the application has
	 * no direct access to TDLib&#039;s file system, because it is usually
	 * slower than a direct read from the file.
	 * <p> Returns {@link FilePart FilePart} </p>
	**/
	public static final class ReadFilePart extends Function<FilePart> {


		/**
		 * Identifier of the file. The file must be located in the TDLib file cache.
		**/
		public int fileId;

		/**
		 * The offset from which to read the file.
		**/
		public long offset;

		/**
		 * Number of bytes to read. An error will be returned if there are not enough bytes available in the file from the specified position. Pass 0 to read all available data from the specified position.
		**/
		public long count;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 906798861;

		/**
		 * Reads a part of a file from the TDLib file cache and returns read bytes. This method is intended to be used only if the application has no direct access to TDLib&#039;s file system, because it is usually slower than a direct read from the file.
		 *
		 * <p> Returns {@link FilePart FilePart} </p>
		**/
		public ReadFilePart() {}

		/**
		 * Reads a part of a file from the TDLib file cache and returns read bytes. This method is intended to be used only if the application has no direct access to TDLib&#039;s file system, because it is usually slower than a direct read from the file.
		 *
		 * <p> Returns {@link FilePart FilePart} </p>
		 *
		 * @param fileId Identifier of the file. The file must be located in the TDLib file cache.
		 * @param offset The offset from which to read the file.
		 * @param count Number of bytes to read. An error will be returned if there are not enough bytes available in the file from the specified position. Pass 0 to read all available data from the specified position.
		 *
		 * <p> Returns {@link FilePart FilePart} </p>
		**/
		public ReadFilePart(int fileId, long offset, long count) {
			this.fileId = fileId;
			this.offset = offset;
			this.count = count;
		}

		/**
		 * Reads a part of a file from the TDLib file cache and returns read bytes. This method is intended to be used only if the application has no direct access to TDLib&#039;s file system, because it is usually slower than a direct read from the file.
		 *
		 * <p> Returns {@link FilePart FilePart} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ReadFilePart(DataInput input) throws IOException {
			this.fileId = input.readInt();
			this.offset = input.readLong();
			this.count = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ReadFilePart.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ReadFilePart.CONSTRUCTOR);
			output.writeInt(this.fileId);
			output.writeLong(this.offset);
			output.writeLong(this.count);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ReadFilePart readFilePart = (ReadFilePart) o;
			if (this.fileId != readFilePart.fileId) {
				return false;
			}
			if (this.offset != readFilePart.offset) {
				return false;
			}
			if (this.count != readFilePart.count) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.fileId);
			return result;
		}
	}

	/**
	 * Recognizes speech in a video note or a voice note message. The
	 * message must be successfully sent and must not be scheduled. May
	 * return an error with a message &quot;MSG_VOICE_TOO_LONG&quot; if
	 * media duration is too big to be recognized.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class RecognizeSpeech extends Function<Ok> {


		/**
		 * Identifier of the chat to which the message belongs.
		**/
		public long chatId;

		/**
		 * Identifier of the message.
		**/
		public long messageId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1741947577;

		/**
		 * Recognizes speech in a video note or a voice note message. The message must be successfully sent and must not be scheduled. May return an error with a message &quot;MSG_VOICE_TOO_LONG&quot; if media duration is too big to be recognized.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public RecognizeSpeech() {}

		/**
		 * Recognizes speech in a video note or a voice note message. The message must be successfully sent and must not be scheduled. May return an error with a message &quot;MSG_VOICE_TOO_LONG&quot; if media duration is too big to be recognized.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Identifier of the chat to which the message belongs.
		 * @param messageId Identifier of the message.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public RecognizeSpeech(long chatId, long messageId) {
			this.chatId = chatId;
			this.messageId = messageId;
		}

		/**
		 * Recognizes speech in a video note or a voice note message. The message must be successfully sent and must not be scheduled. May return an error with a message &quot;MSG_VOICE_TOO_LONG&quot; if media duration is too big to be recognized.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RecognizeSpeech(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RecognizeSpeech.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RecognizeSpeech.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			RecognizeSpeech recognizeSpeech = (RecognizeSpeech) o;
			if (this.chatId != recognizeSpeech.chatId) {
				return false;
			}
			if (this.messageId != recognizeSpeech.messageId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Recovers the 2-step verification password with a password recovery
	 * code sent to an email address that was previously set up. Works only
	 * when the current authorization state is
	 * authorizationStateWaitPassword.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class RecoverAuthenticationPassword extends Function<Ok> {


		/**
		 * Recovery code to check.
		**/
		public String recoveryCode;

		/**
		 * New 2-step verification password of the user; may be empty to remove the password.
		**/
		public String newPassword;

		/**
		 * New password hint; may be empty.
		**/
		public String newHint;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -131001053;

		/**
		 * Recovers the 2-step verification password with a password recovery code sent to an email address that was previously set up. Works only when the current authorization state is authorizationStateWaitPassword.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public RecoverAuthenticationPassword() {}

		/**
		 * Recovers the 2-step verification password with a password recovery code sent to an email address that was previously set up. Works only when the current authorization state is authorizationStateWaitPassword.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param recoveryCode Recovery code to check.
		 * @param newPassword New 2-step verification password of the user; may be empty to remove the password.
		 * @param newHint New password hint; may be empty.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public RecoverAuthenticationPassword(String recoveryCode, String newPassword, String newHint) {
			this.recoveryCode = recoveryCode;
			this.newPassword = newPassword;
			this.newHint = newHint;
		}

		/**
		 * Recovers the 2-step verification password with a password recovery code sent to an email address that was previously set up. Works only when the current authorization state is authorizationStateWaitPassword.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RecoverAuthenticationPassword(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] recoveryCodeTmp = new byte[input.readInt()];
				input.readFully(recoveryCodeTmp);
				this.recoveryCode = new String(recoveryCodeTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] newPasswordTmp = new byte[input.readInt()];
				input.readFully(newPasswordTmp);
				this.newPassword = new String(newPasswordTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] newHintTmp = new byte[input.readInt()];
				input.readFully(newHintTmp);
				this.newHint = new String(newHintTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RecoverAuthenticationPassword.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RecoverAuthenticationPassword.CONSTRUCTOR);
			if (this.recoveryCode == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] recoveryCodeTmp = this.recoveryCode.getBytes(StandardCharsets.UTF_8);
				output.writeInt(recoveryCodeTmp.length);
				output.write(recoveryCodeTmp);
			}
			if (this.newPassword == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] newPasswordTmp = this.newPassword.getBytes(StandardCharsets.UTF_8);
				output.writeInt(newPasswordTmp.length);
				output.write(newPasswordTmp);
			}
			if (this.newHint == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] newHintTmp = this.newHint.getBytes(StandardCharsets.UTF_8);
				output.writeInt(newHintTmp.length);
				output.write(newHintTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			RecoverAuthenticationPassword recoverAuthenticationPassword = (RecoverAuthenticationPassword) o;
			if (this.recoveryCode != recoverAuthenticationPassword.recoveryCode) {
				return false;
			}
			if (this.newPassword != recoverAuthenticationPassword.newPassword) {
				return false;
			}
			if (this.newHint != recoverAuthenticationPassword.newHint) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.recoveryCode == null ? 0 : this.recoveryCode.hashCode();
			result = result * 31 + (this.newPassword == null ? 0 : this.newPassword.hashCode());
			result = result * 31 + (this.newHint == null ? 0 : this.newHint.hashCode());
			return result;
		}
	}

	/**
	 * Recovers the 2-step verification password using a recovery code sent
	 * to an email address that was previously set up.
	 * <p> Returns {@link PasswordState PasswordState} </p>
	**/
	public static final class RecoverPassword extends Function<PasswordState> {


		/**
		 * Recovery code to check.
		**/
		public String recoveryCode;

		/**
		 * New 2-step verification password of the user; may be empty to remove the password.
		**/
		public String newPassword;

		/**
		 * New password hint; may be empty.
		**/
		public String newHint;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1524262541;

		/**
		 * Recovers the 2-step verification password using a recovery code sent to an email address that was previously set up.
		 *
		 * <p> Returns {@link PasswordState PasswordState} </p>
		**/
		public RecoverPassword() {}

		/**
		 * Recovers the 2-step verification password using a recovery code sent to an email address that was previously set up.
		 *
		 * <p> Returns {@link PasswordState PasswordState} </p>
		 *
		 * @param recoveryCode Recovery code to check.
		 * @param newPassword New 2-step verification password of the user; may be empty to remove the password.
		 * @param newHint New password hint; may be empty.
		 *
		 * <p> Returns {@link PasswordState PasswordState} </p>
		**/
		public RecoverPassword(String recoveryCode, String newPassword, String newHint) {
			this.recoveryCode = recoveryCode;
			this.newPassword = newPassword;
			this.newHint = newHint;
		}

		/**
		 * Recovers the 2-step verification password using a recovery code sent to an email address that was previously set up.
		 *
		 * <p> Returns {@link PasswordState PasswordState} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RecoverPassword(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] recoveryCodeTmp = new byte[input.readInt()];
				input.readFully(recoveryCodeTmp);
				this.recoveryCode = new String(recoveryCodeTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] newPasswordTmp = new byte[input.readInt()];
				input.readFully(newPasswordTmp);
				this.newPassword = new String(newPasswordTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] newHintTmp = new byte[input.readInt()];
				input.readFully(newHintTmp);
				this.newHint = new String(newHintTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RecoverPassword.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RecoverPassword.CONSTRUCTOR);
			if (this.recoveryCode == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] recoveryCodeTmp = this.recoveryCode.getBytes(StandardCharsets.UTF_8);
				output.writeInt(recoveryCodeTmp.length);
				output.write(recoveryCodeTmp);
			}
			if (this.newPassword == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] newPasswordTmp = this.newPassword.getBytes(StandardCharsets.UTF_8);
				output.writeInt(newPasswordTmp.length);
				output.write(newPasswordTmp);
			}
			if (this.newHint == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] newHintTmp = this.newHint.getBytes(StandardCharsets.UTF_8);
				output.writeInt(newHintTmp.length);
				output.write(newHintTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			RecoverPassword recoverPassword = (RecoverPassword) o;
			if (this.recoveryCode != recoverPassword.recoveryCode) {
				return false;
			}
			if (this.newPassword != recoverPassword.newPassword) {
				return false;
			}
			if (this.newHint != recoverPassword.newHint) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.recoveryCode == null ? 0 : this.recoveryCode.hashCode();
			result = result * 31 + (this.newPassword == null ? 0 : this.newPassword.hashCode());
			result = result * 31 + (this.newHint == null ? 0 : this.newHint.hashCode());
			return result;
		}
	}

	/**
	 * Registers the currently used device for receiving push notifications.
	 * Returns a globally unique identifier of the push notification
	 * subscription.
	 * <p> Returns {@link PushReceiverId PushReceiverId} </p>
	**/
	public static final class RegisterDevice extends Function<PushReceiverId> {


		/**
		 * Device token.
		**/
		public DeviceToken deviceToken;

		/**
		 * List of user identifiers of other users currently using the application.
		**/
		public long[] otherUserIds;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 366088823;

		/**
		 * Registers the currently used device for receiving push notifications. Returns a globally unique identifier of the push notification subscription.
		 *
		 * <p> Returns {@link PushReceiverId PushReceiverId} </p>
		**/
		public RegisterDevice() {}

		/**
		 * Registers the currently used device for receiving push notifications. Returns a globally unique identifier of the push notification subscription.
		 *
		 * <p> Returns {@link PushReceiverId PushReceiverId} </p>
		 *
		 * @param deviceToken Device token.
		 * @param otherUserIds List of user identifiers of other users currently using the application.
		 *
		 * <p> Returns {@link PushReceiverId PushReceiverId} </p>
		**/
		public RegisterDevice(DeviceToken deviceToken, long[] otherUserIds) {
			this.deviceToken = deviceToken;
			this.otherUserIds = otherUserIds;
		}

		/**
		 * Registers the currently used device for receiving push notifications. Returns a globally unique identifier of the push notification subscription.
		 *
		 * <p> Returns {@link PushReceiverId PushReceiverId} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RegisterDevice(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case DeviceTokenFirebaseCloudMessaging.CONSTRUCTOR: this.deviceToken = new DeviceTokenFirebaseCloudMessaging(input); break;
					case DeviceTokenApplePush.CONSTRUCTOR: this.deviceToken = new DeviceTokenApplePush(input); break;
					case DeviceTokenApplePushVoIP.CONSTRUCTOR: this.deviceToken = new DeviceTokenApplePushVoIP(input); break;
					case DeviceTokenWindowsPush.CONSTRUCTOR: this.deviceToken = new DeviceTokenWindowsPush(input); break;
					case DeviceTokenMicrosoftPush.CONSTRUCTOR: this.deviceToken = new DeviceTokenMicrosoftPush(input); break;
					case DeviceTokenMicrosoftPushVoIP.CONSTRUCTOR: this.deviceToken = new DeviceTokenMicrosoftPushVoIP(input); break;
					case DeviceTokenWebPush.CONSTRUCTOR: this.deviceToken = new DeviceTokenWebPush(input); break;
					case DeviceTokenSimplePush.CONSTRUCTOR: this.deviceToken = new DeviceTokenSimplePush(input); break;
					case DeviceTokenUbuntuPush.CONSTRUCTOR: this.deviceToken = new DeviceTokenUbuntuPush(input); break;
					case DeviceTokenBlackBerryPush.CONSTRUCTOR: this.deviceToken = new DeviceTokenBlackBerryPush(input); break;
					case DeviceTokenTizenPush.CONSTRUCTOR: this.deviceToken = new DeviceTokenTizenPush(input); break;
					case DeviceTokenHuaweiPush.CONSTRUCTOR: this.deviceToken = new DeviceTokenHuaweiPush(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				this.otherUserIds = new long[input.readInt()];
				for (int i = 0; i < this.otherUserIds.length; i++) {
					this.otherUserIds[i] = input.readLong();
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RegisterDevice.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RegisterDevice.CONSTRUCTOR);
			if (this.deviceToken == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.deviceToken.serialize(output);
			}
			if (this.otherUserIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.otherUserIds.length);
				for (int i = 0; i < this.otherUserIds.length; i++) {
					output.writeLong(this.otherUserIds[i]);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			RegisterDevice registerDevice = (RegisterDevice) o;
			if (!Objects.equals(this.deviceToken, registerDevice.deviceToken)) {
				return false;
			}
			if (!Arrays.equals(this.otherUserIds, registerDevice.otherUserIds)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.deviceToken == null ? 0 : this.deviceToken.hashCode();
			result = result * 31 + (Arrays.hashCode(this.otherUserIds));
			return result;
		}
	}

	/**
	 * Finishes user registration. Works only when the current authorization
	 * state is authorizationStateWaitRegistration.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class RegisterUser extends Function<Ok> {


		/**
		 * The first name of the user; 1-64 characters.
		**/
		public String firstName;

		/**
		 * The last name of the user; 0-64 characters.
		**/
		public String lastName;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -109994467;

		/**
		 * Finishes user registration. Works only when the current authorization state is authorizationStateWaitRegistration.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public RegisterUser() {}

		/**
		 * Finishes user registration. Works only when the current authorization state is authorizationStateWaitRegistration.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param firstName The first name of the user; 1-64 characters.
		 * @param lastName The last name of the user; 0-64 characters.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public RegisterUser(String firstName, String lastName) {
			this.firstName = firstName;
			this.lastName = lastName;
		}

		/**
		 * Finishes user registration. Works only when the current authorization state is authorizationStateWaitRegistration.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RegisterUser(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] firstNameTmp = new byte[input.readInt()];
				input.readFully(firstNameTmp);
				this.firstName = new String(firstNameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] lastNameTmp = new byte[input.readInt()];
				input.readFully(lastNameTmp);
				this.lastName = new String(lastNameTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RegisterUser.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RegisterUser.CONSTRUCTOR);
			if (this.firstName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] firstNameTmp = this.firstName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(firstNameTmp.length);
				output.write(firstNameTmp);
			}
			if (this.lastName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] lastNameTmp = this.lastName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(lastNameTmp.length);
				output.write(lastNameTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			RegisterUser registerUser = (RegisterUser) o;
			if (this.firstName != registerUser.firstName) {
				return false;
			}
			if (this.lastName != registerUser.lastName) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.firstName == null ? 0 : this.firstName.hashCode();
			result = result * 31 + (this.lastName == null ? 0 : this.lastName.hashCode());
			return result;
		}
	}

	/**
	 * Removes all files from the file download list.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class RemoveAllFilesFromDownloads extends Function<Ok> {


		/**
		 * Pass true to remove only active downloads, including paused.
		**/
		public boolean onlyActive;

		/**
		 * Pass true to remove only completed downloads.
		**/
		public boolean onlyCompleted;

		/**
		 * Pass true to delete the file from the TDLib file cache.
		**/
		public boolean deleteFromCache;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1186433402;

		/**
		 * Removes all files from the file download list.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public RemoveAllFilesFromDownloads() {}

		/**
		 * Removes all files from the file download list.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param onlyActive Pass true to remove only active downloads, including paused.
		 * @param onlyCompleted Pass true to remove only completed downloads.
		 * @param deleteFromCache Pass true to delete the file from the TDLib file cache.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public RemoveAllFilesFromDownloads(boolean onlyActive,
				boolean onlyCompleted,
				boolean deleteFromCache) {
			this.onlyActive = onlyActive;
			this.onlyCompleted = onlyCompleted;
			this.deleteFromCache = deleteFromCache;
		}

		/**
		 * Removes all files from the file download list.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RemoveAllFilesFromDownloads(DataInput input) throws IOException {
			this.onlyActive = input.readBoolean();
			this.onlyCompleted = input.readBoolean();
			this.deleteFromCache = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RemoveAllFilesFromDownloads.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RemoveAllFilesFromDownloads.CONSTRUCTOR);
			output.writeBoolean(this.onlyActive);
			output.writeBoolean(this.onlyCompleted);
			output.writeBoolean(this.deleteFromCache);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			RemoveAllFilesFromDownloads removeAllFilesFromDownloads = (RemoveAllFilesFromDownloads) o;
			if (this.onlyActive != removeAllFilesFromDownloads.onlyActive) {
				return false;
			}
			if (this.onlyCompleted != removeAllFilesFromDownloads.onlyCompleted) {
				return false;
			}
			if (this.deleteFromCache != removeAllFilesFromDownloads.deleteFromCache) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.onlyActive);
			return result;
		}
	}

	/**
	 * Removes background from the list of installed backgrounds.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class RemoveBackground extends Function<Ok> {


		/**
		 * The background identifier.
		**/
		public long backgroundId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1484545642;

		/**
		 * Removes background from the list of installed backgrounds.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public RemoveBackground() {}

		/**
		 * Removes background from the list of installed backgrounds.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param backgroundId The background identifier.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public RemoveBackground(long backgroundId) {
			this.backgroundId = backgroundId;
		}

		/**
		 * Removes background from the list of installed backgrounds.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RemoveBackground(DataInput input) throws IOException {
			this.backgroundId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RemoveBackground.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RemoveBackground.CONSTRUCTOR);
			output.writeLong(this.backgroundId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			RemoveBackground removeBackground = (RemoveBackground) o;
			if (this.backgroundId != removeBackground.backgroundId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.backgroundId);
		}
	}

	/**
	 * Removes a chat action bar without any other action.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class RemoveChatActionBar extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1650968070;

		/**
		 * Removes a chat action bar without any other action.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public RemoveChatActionBar() {}

		/**
		 * Removes a chat action bar without any other action.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public RemoveChatActionBar(long chatId) {
			this.chatId = chatId;
		}

		/**
		 * Removes a chat action bar without any other action.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RemoveChatActionBar(DataInput input) throws IOException {
			this.chatId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RemoveChatActionBar.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RemoveChatActionBar.CONSTRUCTOR);
			output.writeLong(this.chatId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			RemoveChatActionBar removeChatActionBar = (RemoveChatActionBar) o;
			if (this.chatId != removeChatActionBar.chatId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.chatId);
		}
	}

	/**
	 * Removes users from the contact list.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class RemoveContacts extends Function<Ok> {


		/**
		 * Identifiers of users to be deleted.
		**/
		public long[] userIds;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1943858054;

		/**
		 * Removes users from the contact list.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public RemoveContacts() {}

		/**
		 * Removes users from the contact list.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param userIds Identifiers of users to be deleted.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public RemoveContacts(long[] userIds) {
			this.userIds = userIds;
		}

		/**
		 * Removes users from the contact list.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RemoveContacts(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.userIds = new long[input.readInt()];
				for (int i = 0; i < this.userIds.length; i++) {
					this.userIds[i] = input.readLong();
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RemoveContacts.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RemoveContacts.CONSTRUCTOR);
			if (this.userIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.userIds.length);
				for (int i = 0; i < this.userIds.length; i++) {
					output.writeLong(this.userIds[i]);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			RemoveContacts removeContacts = (RemoveContacts) o;
			if (!Arrays.equals(this.userIds, removeContacts.userIds)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.userIds);
		}
	}

	/**
	 * Removes a sticker from the list of favorite stickers.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class RemoveFavoriteSticker extends Function<Ok> {


		/**
		 * Sticker file to delete from the list.
		**/
		public InputFile sticker;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1152945264;

		/**
		 * Removes a sticker from the list of favorite stickers.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public RemoveFavoriteSticker() {}

		/**
		 * Removes a sticker from the list of favorite stickers.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param sticker Sticker file to delete from the list.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public RemoveFavoriteSticker(InputFile sticker) {
			this.sticker = sticker;
		}

		/**
		 * Removes a sticker from the list of favorite stickers.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RemoveFavoriteSticker(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputFileId.CONSTRUCTOR: this.sticker = new InputFileId(input); break;
					case InputFileRemote.CONSTRUCTOR: this.sticker = new InputFileRemote(input); break;
					case InputFileLocal.CONSTRUCTOR: this.sticker = new InputFileLocal(input); break;
					case InputFileGenerated.CONSTRUCTOR: this.sticker = new InputFileGenerated(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RemoveFavoriteSticker.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RemoveFavoriteSticker.CONSTRUCTOR);
			if (this.sticker == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.sticker.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			RemoveFavoriteSticker removeFavoriteSticker = (RemoveFavoriteSticker) o;
			if (!Objects.equals(this.sticker, removeFavoriteSticker.sticker)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.sticker == null ? 0 : this.sticker.hashCode();
		}
	}

	/**
	 * Removes a file from the file download list.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class RemoveFileFromDownloads extends Function<Ok> {


		/**
		 * Identifier of the downloaded file.
		**/
		public int fileId;

		/**
		 * Pass true to delete the file from the TDLib file cache.
		**/
		public boolean deleteFromCache;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1460060142;

		/**
		 * Removes a file from the file download list.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public RemoveFileFromDownloads() {}

		/**
		 * Removes a file from the file download list.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param fileId Identifier of the downloaded file.
		 * @param deleteFromCache Pass true to delete the file from the TDLib file cache.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public RemoveFileFromDownloads(int fileId, boolean deleteFromCache) {
			this.fileId = fileId;
			this.deleteFromCache = deleteFromCache;
		}

		/**
		 * Removes a file from the file download list.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RemoveFileFromDownloads(DataInput input) throws IOException {
			this.fileId = input.readInt();
			this.deleteFromCache = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RemoveFileFromDownloads.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RemoveFileFromDownloads.CONSTRUCTOR);
			output.writeInt(this.fileId);
			output.writeBoolean(this.deleteFromCache);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			RemoveFileFromDownloads removeFileFromDownloads = (RemoveFileFromDownloads) o;
			if (this.fileId != removeFileFromDownloads.fileId) {
				return false;
			}
			if (this.deleteFromCache != removeFileFromDownloads.deleteFromCache) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.fileId);
			return result;
		}
	}

	/**
	 * Removes a reaction from a message. A chosen reaction can always be
	 * removed.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class RemoveMessageReaction extends Function<Ok> {


		/**
		 * Identifier of the chat to which the message belongs.
		**/
		public long chatId;

		/**
		 * Identifier of the message.
		**/
		public long messageId;

		/**
		 * Type of the reaction to remove.
		**/
		public ReactionType reactionType;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1756934789;

		/**
		 * Removes a reaction from a message. A chosen reaction can always be removed.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public RemoveMessageReaction() {}

		/**
		 * Removes a reaction from a message. A chosen reaction can always be removed.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Identifier of the chat to which the message belongs.
		 * @param messageId Identifier of the message.
		 * @param reactionType Type of the reaction to remove.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public RemoveMessageReaction(long chatId, long messageId, ReactionType reactionType) {
			this.chatId = chatId;
			this.messageId = messageId;
			this.reactionType = reactionType;
		}

		/**
		 * Removes a reaction from a message. A chosen reaction can always be removed.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RemoveMessageReaction(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ReactionTypeEmoji.CONSTRUCTOR: this.reactionType = new ReactionTypeEmoji(input); break;
					case ReactionTypeCustomEmoji.CONSTRUCTOR: this.reactionType = new ReactionTypeCustomEmoji(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RemoveMessageReaction.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RemoveMessageReaction.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
			if (this.reactionType == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.reactionType.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			RemoveMessageReaction removeMessageReaction = (RemoveMessageReaction) o;
			if (this.chatId != removeMessageReaction.chatId) {
				return false;
			}
			if (this.messageId != removeMessageReaction.messageId) {
				return false;
			}
			if (!Objects.equals(this.reactionType, removeMessageReaction.reactionType)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.reactionType == null ? 0 : this.reactionType.hashCode());
			return result;
		}
	}

	/**
	 * Removes an active notification from notification list. Needs to be
	 * called only if the notification is removed by the current user.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class RemoveNotification extends Function<Ok> {


		/**
		 * Identifier of notification group to which the notification belongs.
		**/
		public int notificationGroupId;

		/**
		 * Identifier of removed notification.
		**/
		public int notificationId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 862630734;

		/**
		 * Removes an active notification from notification list. Needs to be called only if the notification is removed by the current user.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public RemoveNotification() {}

		/**
		 * Removes an active notification from notification list. Needs to be called only if the notification is removed by the current user.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param notificationGroupId Identifier of notification group to which the notification belongs.
		 * @param notificationId Identifier of removed notification.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public RemoveNotification(int notificationGroupId, int notificationId) {
			this.notificationGroupId = notificationGroupId;
			this.notificationId = notificationId;
		}

		/**
		 * Removes an active notification from notification list. Needs to be called only if the notification is removed by the current user.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RemoveNotification(DataInput input) throws IOException {
			this.notificationGroupId = input.readInt();
			this.notificationId = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RemoveNotification.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RemoveNotification.CONSTRUCTOR);
			output.writeInt(this.notificationGroupId);
			output.writeInt(this.notificationId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			RemoveNotification removeNotification = (RemoveNotification) o;
			if (this.notificationGroupId != removeNotification.notificationGroupId) {
				return false;
			}
			if (this.notificationId != removeNotification.notificationId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.notificationGroupId);
			return result;
		}
	}

	/**
	 * Removes a group of active notifications. Needs to be called only if
	 * the notification group is removed by the current user.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class RemoveNotificationGroup extends Function<Ok> {


		/**
		 * Notification group identifier.
		**/
		public int notificationGroupId;

		/**
		 * The maximum identifier of removed notifications.
		**/
		public int maxNotificationId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1713005454;

		/**
		 * Removes a group of active notifications. Needs to be called only if the notification group is removed by the current user.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public RemoveNotificationGroup() {}

		/**
		 * Removes a group of active notifications. Needs to be called only if the notification group is removed by the current user.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param notificationGroupId Notification group identifier.
		 * @param maxNotificationId The maximum identifier of removed notifications.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public RemoveNotificationGroup(int notificationGroupId, int maxNotificationId) {
			this.notificationGroupId = notificationGroupId;
			this.maxNotificationId = maxNotificationId;
		}

		/**
		 * Removes a group of active notifications. Needs to be called only if the notification group is removed by the current user.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RemoveNotificationGroup(DataInput input) throws IOException {
			this.notificationGroupId = input.readInt();
			this.maxNotificationId = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RemoveNotificationGroup.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RemoveNotificationGroup.CONSTRUCTOR);
			output.writeInt(this.notificationGroupId);
			output.writeInt(this.maxNotificationId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			RemoveNotificationGroup removeNotificationGroup = (RemoveNotificationGroup) o;
			if (this.notificationGroupId != removeNotificationGroup.notificationGroupId) {
				return false;
			}
			if (this.maxNotificationId != removeNotificationGroup.maxNotificationId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.notificationGroupId);
			return result;
		}
	}

	/**
	 * Removes a proxy server. Can be called before authorization.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class RemoveProxy extends Function<Ok> {


		/**
		 * Proxy identifier.
		**/
		public int proxyId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1369219847;

		/**
		 * Removes a proxy server. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public RemoveProxy() {}

		/**
		 * Removes a proxy server. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param proxyId Proxy identifier.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public RemoveProxy(int proxyId) {
			this.proxyId = proxyId;
		}

		/**
		 * Removes a proxy server. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RemoveProxy(DataInput input) throws IOException {
			this.proxyId = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RemoveProxy.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RemoveProxy.CONSTRUCTOR);
			output.writeInt(this.proxyId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			RemoveProxy removeProxy = (RemoveProxy) o;
			if (this.proxyId != removeProxy.proxyId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.proxyId);
		}
	}

	/**
	 * Removes a hashtag from the list of recently used hashtags.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class RemoveRecentHashtag extends Function<Ok> {


		/**
		 * Hashtag to delete.
		**/
		public String hashtag;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1013735260;

		/**
		 * Removes a hashtag from the list of recently used hashtags.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public RemoveRecentHashtag() {}

		/**
		 * Removes a hashtag from the list of recently used hashtags.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param hashtag Hashtag to delete.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public RemoveRecentHashtag(String hashtag) {
			this.hashtag = hashtag;
		}

		/**
		 * Removes a hashtag from the list of recently used hashtags.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RemoveRecentHashtag(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] hashtagTmp = new byte[input.readInt()];
				input.readFully(hashtagTmp);
				this.hashtag = new String(hashtagTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RemoveRecentHashtag.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RemoveRecentHashtag.CONSTRUCTOR);
			if (this.hashtag == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] hashtagTmp = this.hashtag.getBytes(StandardCharsets.UTF_8);
				output.writeInt(hashtagTmp.length);
				output.write(hashtagTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			RemoveRecentHashtag removeRecentHashtag = (RemoveRecentHashtag) o;
			if (this.hashtag != removeRecentHashtag.hashtag) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.hashtag == null ? 0 : this.hashtag.hashCode();
		}
	}

	/**
	 * Removes a sticker from the list of recently used stickers.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class RemoveRecentSticker extends Function<Ok> {


		/**
		 * Pass true to remove the sticker from the list of stickers recently attached to photo or video files; pass false to remove the sticker from the list of recently sent stickers.
		**/
		public boolean isAttached;

		/**
		 * Sticker file to delete.
		**/
		public InputFile sticker;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1246577677;

		/**
		 * Removes a sticker from the list of recently used stickers.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public RemoveRecentSticker() {}

		/**
		 * Removes a sticker from the list of recently used stickers.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param isAttached Pass true to remove the sticker from the list of stickers recently attached to photo or video files; pass false to remove the sticker from the list of recently sent stickers.
		 * @param sticker Sticker file to delete.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public RemoveRecentSticker(boolean isAttached, InputFile sticker) {
			this.isAttached = isAttached;
			this.sticker = sticker;
		}

		/**
		 * Removes a sticker from the list of recently used stickers.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RemoveRecentSticker(DataInput input) throws IOException {
			this.isAttached = input.readBoolean();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputFileId.CONSTRUCTOR: this.sticker = new InputFileId(input); break;
					case InputFileRemote.CONSTRUCTOR: this.sticker = new InputFileRemote(input); break;
					case InputFileLocal.CONSTRUCTOR: this.sticker = new InputFileLocal(input); break;
					case InputFileGenerated.CONSTRUCTOR: this.sticker = new InputFileGenerated(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RemoveRecentSticker.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RemoveRecentSticker.CONSTRUCTOR);
			output.writeBoolean(this.isAttached);
			if (this.sticker == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.sticker.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			RemoveRecentSticker removeRecentSticker = (RemoveRecentSticker) o;
			if (this.isAttached != removeRecentSticker.isAttached) {
				return false;
			}
			if (!Objects.equals(this.sticker, removeRecentSticker.sticker)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isAttached);
			result = result * 31 + (this.sticker == null ? 0 : this.sticker.hashCode());
			return result;
		}
	}

	/**
	 * Removes a chat from the list of recently found chats.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class RemoveRecentlyFoundChat extends Function<Ok> {


		/**
		 * Identifier of the chat to be removed.
		**/
		public long chatId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 717340444;

		/**
		 * Removes a chat from the list of recently found chats.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public RemoveRecentlyFoundChat() {}

		/**
		 * Removes a chat from the list of recently found chats.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Identifier of the chat to be removed.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public RemoveRecentlyFoundChat(long chatId) {
			this.chatId = chatId;
		}

		/**
		 * Removes a chat from the list of recently found chats.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RemoveRecentlyFoundChat(DataInput input) throws IOException {
			this.chatId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RemoveRecentlyFoundChat.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RemoveRecentlyFoundChat.CONSTRUCTOR);
			output.writeLong(this.chatId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			RemoveRecentlyFoundChat removeRecentlyFoundChat = (RemoveRecentlyFoundChat) o;
			if (this.chatId != removeRecentlyFoundChat.chatId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.chatId);
		}
	}

	/**
	 * Removes an animation from the list of saved animations.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class RemoveSavedAnimation extends Function<Ok> {


		/**
		 * Animation file to be removed.
		**/
		public InputFile animation;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -495605479;

		/**
		 * Removes an animation from the list of saved animations.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public RemoveSavedAnimation() {}

		/**
		 * Removes an animation from the list of saved animations.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param animation Animation file to be removed.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public RemoveSavedAnimation(InputFile animation) {
			this.animation = animation;
		}

		/**
		 * Removes an animation from the list of saved animations.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RemoveSavedAnimation(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputFileId.CONSTRUCTOR: this.animation = new InputFileId(input); break;
					case InputFileRemote.CONSTRUCTOR: this.animation = new InputFileRemote(input); break;
					case InputFileLocal.CONSTRUCTOR: this.animation = new InputFileLocal(input); break;
					case InputFileGenerated.CONSTRUCTOR: this.animation = new InputFileGenerated(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RemoveSavedAnimation.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RemoveSavedAnimation.CONSTRUCTOR);
			if (this.animation == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.animation.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			RemoveSavedAnimation removeSavedAnimation = (RemoveSavedAnimation) o;
			if (!Objects.equals(this.animation, removeSavedAnimation.animation)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.animation == null ? 0 : this.animation.hashCode();
		}
	}

	/**
	 * Removes a notification sound from the list of saved notification
	 * sounds.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class RemoveSavedNotificationSound extends Function<Ok> {


		/**
		 * Identifier of the notification sound.
		**/
		public long notificationSoundId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -480032946;

		/**
		 * Removes a notification sound from the list of saved notification sounds.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public RemoveSavedNotificationSound() {}

		/**
		 * Removes a notification sound from the list of saved notification sounds.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param notificationSoundId Identifier of the notification sound.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public RemoveSavedNotificationSound(long notificationSoundId) {
			this.notificationSoundId = notificationSoundId;
		}

		/**
		 * Removes a notification sound from the list of saved notification sounds.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RemoveSavedNotificationSound(DataInput input) throws IOException {
			this.notificationSoundId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RemoveSavedNotificationSound.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RemoveSavedNotificationSound.CONSTRUCTOR);
			output.writeLong(this.notificationSoundId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			RemoveSavedNotificationSound removeSavedNotificationSound = (RemoveSavedNotificationSound) o;
			if (this.notificationSoundId != removeSavedNotificationSound.notificationSoundId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.notificationSoundId);
		}
	}

	/**
	 * Removes a sticker from the set to which it belongs; for bots only.
	 * The sticker set must have been created by the bot.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class RemoveStickerFromSet extends Function<Ok> {


		/**
		 * Sticker.
		**/
		public InputFile sticker;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1642196644;

		/**
		 * Removes a sticker from the set to which it belongs; for bots only. The sticker set must have been created by the bot.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public RemoveStickerFromSet() {}

		/**
		 * Removes a sticker from the set to which it belongs; for bots only. The sticker set must have been created by the bot.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param sticker Sticker.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public RemoveStickerFromSet(InputFile sticker) {
			this.sticker = sticker;
		}

		/**
		 * Removes a sticker from the set to which it belongs; for bots only. The sticker set must have been created by the bot.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RemoveStickerFromSet(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputFileId.CONSTRUCTOR: this.sticker = new InputFileId(input); break;
					case InputFileRemote.CONSTRUCTOR: this.sticker = new InputFileRemote(input); break;
					case InputFileLocal.CONSTRUCTOR: this.sticker = new InputFileLocal(input); break;
					case InputFileGenerated.CONSTRUCTOR: this.sticker = new InputFileGenerated(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RemoveStickerFromSet.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RemoveStickerFromSet.CONSTRUCTOR);
			if (this.sticker == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.sticker.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			RemoveStickerFromSet removeStickerFromSet = (RemoveStickerFromSet) o;
			if (!Objects.equals(this.sticker, removeStickerFromSet.sticker)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.sticker == null ? 0 : this.sticker.hashCode();
		}
	}

	/**
	 * Removes a chat from the list of frequently used chats. Supported only
	 * if the chat info database is enabled.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class RemoveTopChat extends Function<Ok> {


		/**
		 * Category of frequently used chats.
		**/
		public TopChatCategory category;

		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1907876267;

		/**
		 * Removes a chat from the list of frequently used chats. Supported only if the chat info database is enabled.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public RemoveTopChat() {}

		/**
		 * Removes a chat from the list of frequently used chats. Supported only if the chat info database is enabled.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param category Category of frequently used chats.
		 * @param chatId Chat identifier.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public RemoveTopChat(TopChatCategory category, long chatId) {
			this.category = category;
			this.chatId = chatId;
		}

		/**
		 * Removes a chat from the list of frequently used chats. Supported only if the chat info database is enabled.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RemoveTopChat(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case TopChatCategoryUsers.CONSTRUCTOR: this.category = new TopChatCategoryUsers(input); break;
					case TopChatCategoryBots.CONSTRUCTOR: this.category = new TopChatCategoryBots(input); break;
					case TopChatCategoryGroups.CONSTRUCTOR: this.category = new TopChatCategoryGroups(input); break;
					case TopChatCategoryChannels.CONSTRUCTOR: this.category = new TopChatCategoryChannels(input); break;
					case TopChatCategoryInlineBots.CONSTRUCTOR: this.category = new TopChatCategoryInlineBots(input); break;
					case TopChatCategoryCalls.CONSTRUCTOR: this.category = new TopChatCategoryCalls(input); break;
					case TopChatCategoryForwardChats.CONSTRUCTOR: this.category = new TopChatCategoryForwardChats(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.chatId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RemoveTopChat.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RemoveTopChat.CONSTRUCTOR);
			if (this.category == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.category.serialize(output);
			}
			output.writeLong(this.chatId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			RemoveTopChat removeTopChat = (RemoveTopChat) o;
			if (!Objects.equals(this.category, removeTopChat.category)) {
				return false;
			}
			if (this.chatId != removeTopChat.chatId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.category == null ? 0 : this.category.hashCode());
			return result;
		}
	}

	/**
	 * Changes order of active usernames of a bot. Can be called only if
	 * userTypeBot.canBeEdited == true.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ReorderActiveBotUsernames extends Function<Ok> {


		/**
		 * Identifier of the target bot.
		**/
		public long botUserId;

		/**
		 * The new order of active usernames. All currently active usernames must be specified.
		**/
		public String[] usernames;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1801166592;

		/**
		 * Changes order of active usernames of a bot. Can be called only if userTypeBot.canBeEdited == true.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ReorderActiveBotUsernames() {}

		/**
		 * Changes order of active usernames of a bot. Can be called only if userTypeBot.canBeEdited == true.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param botUserId Identifier of the target bot.
		 * @param usernames The new order of active usernames. All currently active usernames must be specified.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ReorderActiveBotUsernames(long botUserId, String[] usernames) {
			this.botUserId = botUserId;
			this.usernames = usernames;
		}

		/**
		 * Changes order of active usernames of a bot. Can be called only if userTypeBot.canBeEdited == true.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ReorderActiveBotUsernames(DataInput input) throws IOException {
			this.botUserId = input.readLong();
			if (input.readBoolean()) {
				this.usernames = new String[input.readInt()];
				for (int i = 0; i < this.usernames.length; i++) {
					byte[] usernamesTmp = new byte[input.readInt()];
					input.readFully(usernamesTmp);
					this.usernames[i] = new String(usernamesTmp, StandardCharsets.UTF_8);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ReorderActiveBotUsernames.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ReorderActiveBotUsernames.CONSTRUCTOR);
			output.writeLong(this.botUserId);
			if (this.usernames == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.usernames.length);
				for (int i = 0; i < this.usernames.length; i++) {
					byte[] usernamesTmp = this.usernames[i].getBytes(StandardCharsets.UTF_8);
					output.writeInt(usernamesTmp.length);
					output.write(usernamesTmp);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ReorderActiveBotUsernames reorderActiveBotUsernames = (ReorderActiveBotUsernames) o;
			if (this.botUserId != reorderActiveBotUsernames.botUserId) {
				return false;
			}
			if (!Arrays.equals(this.usernames, reorderActiveBotUsernames.usernames)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.botUserId);
			result = result * 31 + (Arrays.hashCode(this.usernames));
			return result;
		}
	}

	/**
	 * Changes order of active usernames of the current user.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ReorderActiveUsernames extends Function<Ok> {


		/**
		 * The new order of active usernames. All currently active usernames must be specified.
		**/
		public String[] usernames;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -455399375;

		/**
		 * Changes order of active usernames of the current user.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ReorderActiveUsernames() {}

		/**
		 * Changes order of active usernames of the current user.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param usernames The new order of active usernames. All currently active usernames must be specified.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ReorderActiveUsernames(String[] usernames) {
			this.usernames = usernames;
		}

		/**
		 * Changes order of active usernames of the current user.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ReorderActiveUsernames(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.usernames = new String[input.readInt()];
				for (int i = 0; i < this.usernames.length; i++) {
					byte[] usernamesTmp = new byte[input.readInt()];
					input.readFully(usernamesTmp);
					this.usernames[i] = new String(usernamesTmp, StandardCharsets.UTF_8);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ReorderActiveUsernames.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ReorderActiveUsernames.CONSTRUCTOR);
			if (this.usernames == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.usernames.length);
				for (int i = 0; i < this.usernames.length; i++) {
					byte[] usernamesTmp = this.usernames[i].getBytes(StandardCharsets.UTF_8);
					output.writeInt(usernamesTmp.length);
					output.write(usernamesTmp);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ReorderActiveUsernames reorderActiveUsernames = (ReorderActiveUsernames) o;
			if (!Arrays.equals(this.usernames, reorderActiveUsernames.usernames)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.usernames);
		}
	}

	/**
	 * Changes the order of chat folders.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ReorderChatFolders extends Function<Ok> {


		/**
		 * Identifiers of chat folders in the new correct order.
		**/
		public int[] chatFolderIds;

		/**
		 * Position of the main chat list among chat folders, 0-based. Can be non-zero only for Premium users.
		**/
		public int mainChatListPosition;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1665299546;

		/**
		 * Changes the order of chat folders.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ReorderChatFolders() {}

		/**
		 * Changes the order of chat folders.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatFolderIds Identifiers of chat folders in the new correct order.
		 * @param mainChatListPosition Position of the main chat list among chat folders, 0-based. Can be non-zero only for Premium users.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ReorderChatFolders(int[] chatFolderIds, int mainChatListPosition) {
			this.chatFolderIds = chatFolderIds;
			this.mainChatListPosition = mainChatListPosition;
		}

		/**
		 * Changes the order of chat folders.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ReorderChatFolders(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.chatFolderIds = new int[input.readInt()];
				for (int i = 0; i < this.chatFolderIds.length; i++) {
					this.chatFolderIds[i] = input.readInt();
				}
			}
			this.mainChatListPosition = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ReorderChatFolders.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ReorderChatFolders.CONSTRUCTOR);
			if (this.chatFolderIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.chatFolderIds.length);
				for (int i = 0; i < this.chatFolderIds.length; i++) {
					output.writeInt(this.chatFolderIds[i]);
				}
			}
			output.writeInt(this.mainChatListPosition);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ReorderChatFolders reorderChatFolders = (ReorderChatFolders) o;
			if (!Arrays.equals(this.chatFolderIds, reorderChatFolders.chatFolderIds)) {
				return false;
			}
			if (this.mainChatListPosition != reorderChatFolders.mainChatListPosition) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.mainChatListPosition);
			result = result * 31 + (Arrays.hashCode(this.chatFolderIds));
			return result;
		}
	}

	/**
	 * Changes the order of installed sticker sets.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ReorderInstalledStickerSets extends Function<Ok> {


		/**
		 * Type of the sticker sets to reorder.
		**/
		public StickerType stickerType;

		/**
		 * Identifiers of installed sticker sets in the new correct order.
		**/
		public long[] stickerSetIds;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1074928158;

		/**
		 * Changes the order of installed sticker sets.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ReorderInstalledStickerSets() {}

		/**
		 * Changes the order of installed sticker sets.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param stickerType Type of the sticker sets to reorder.
		 * @param stickerSetIds Identifiers of installed sticker sets in the new correct order.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ReorderInstalledStickerSets(StickerType stickerType, long[] stickerSetIds) {
			this.stickerType = stickerType;
			this.stickerSetIds = stickerSetIds;
		}

		/**
		 * Changes the order of installed sticker sets.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ReorderInstalledStickerSets(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case StickerTypeRegular.CONSTRUCTOR: this.stickerType = new StickerTypeRegular(input); break;
					case StickerTypeMask.CONSTRUCTOR: this.stickerType = new StickerTypeMask(input); break;
					case StickerTypeCustomEmoji.CONSTRUCTOR: this.stickerType = new StickerTypeCustomEmoji(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				this.stickerSetIds = new long[input.readInt()];
				for (int i = 0; i < this.stickerSetIds.length; i++) {
					this.stickerSetIds[i] = input.readLong();
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ReorderInstalledStickerSets.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ReorderInstalledStickerSets.CONSTRUCTOR);
			if (this.stickerType == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.stickerType.serialize(output);
			}
			if (this.stickerSetIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.stickerSetIds.length);
				for (int i = 0; i < this.stickerSetIds.length; i++) {
					output.writeLong(this.stickerSetIds[i]);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ReorderInstalledStickerSets reorderInstalledStickerSets = (ReorderInstalledStickerSets) o;
			if (!Objects.equals(this.stickerType, reorderInstalledStickerSets.stickerType)) {
				return false;
			}
			if (!Arrays.equals(this.stickerSetIds, reorderInstalledStickerSets.stickerSetIds)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.stickerType == null ? 0 : this.stickerType.hashCode();
			result = result * 31 + (Arrays.hashCode(this.stickerSetIds));
			return result;
		}
	}

	/**
	 * Changes order of active usernames of a supergroup or channel,
	 * requires owner privileges in the supergroup or channel.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ReorderSupergroupActiveUsernames extends Function<Ok> {


		/**
		 * Identifier of the supergroup or channel.
		**/
		public long supergroupId;

		/**
		 * The new order of active usernames. All currently active usernames must be specified.
		**/
		public String[] usernames;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1962466095;

		/**
		 * Changes order of active usernames of a supergroup or channel, requires owner privileges in the supergroup or channel.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ReorderSupergroupActiveUsernames() {}

		/**
		 * Changes order of active usernames of a supergroup or channel, requires owner privileges in the supergroup or channel.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param supergroupId Identifier of the supergroup or channel.
		 * @param usernames The new order of active usernames. All currently active usernames must be specified.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ReorderSupergroupActiveUsernames(long supergroupId, String[] usernames) {
			this.supergroupId = supergroupId;
			this.usernames = usernames;
		}

		/**
		 * Changes order of active usernames of a supergroup or channel, requires owner privileges in the supergroup or channel.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ReorderSupergroupActiveUsernames(DataInput input) throws IOException {
			this.supergroupId = input.readLong();
			if (input.readBoolean()) {
				this.usernames = new String[input.readInt()];
				for (int i = 0; i < this.usernames.length; i++) {
					byte[] usernamesTmp = new byte[input.readInt()];
					input.readFully(usernamesTmp);
					this.usernames[i] = new String(usernamesTmp, StandardCharsets.UTF_8);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ReorderSupergroupActiveUsernames.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ReorderSupergroupActiveUsernames.CONSTRUCTOR);
			output.writeLong(this.supergroupId);
			if (this.usernames == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.usernames.length);
				for (int i = 0; i < this.usernames.length; i++) {
					byte[] usernamesTmp = this.usernames[i].getBytes(StandardCharsets.UTF_8);
					output.writeInt(usernamesTmp.length);
					output.write(usernamesTmp);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ReorderSupergroupActiveUsernames reorderSupergroupActiveUsernames = (ReorderSupergroupActiveUsernames) o;
			if (this.supergroupId != reorderSupergroupActiveUsernames.supergroupId) {
				return false;
			}
			if (!Arrays.equals(this.usernames, reorderSupergroupActiveUsernames.usernames)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.supergroupId);
			result = result * 31 + (Arrays.hashCode(this.usernames));
			return result;
		}
	}

	/**
	 * Replaces current primary invite link for a chat with a new primary
	 * invite link. Available for basic groups, supergroups, and channels.
	 * Requires administrator privileges and canInviteUsers right.
	 * <p> Returns {@link ChatInviteLink ChatInviteLink} </p>
	**/
	public static final class ReplacePrimaryChatInviteLink extends Function<ChatInviteLink> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1067350941;

		/**
		 * Replaces current primary invite link for a chat with a new primary invite link. Available for basic groups, supergroups, and channels. Requires administrator privileges and canInviteUsers right.
		 *
		 * <p> Returns {@link ChatInviteLink ChatInviteLink} </p>
		**/
		public ReplacePrimaryChatInviteLink() {}

		/**
		 * Replaces current primary invite link for a chat with a new primary invite link. Available for basic groups, supergroups, and channels. Requires administrator privileges and canInviteUsers right.
		 *
		 * <p> Returns {@link ChatInviteLink ChatInviteLink} </p>
		 *
		 * @param chatId Chat identifier.
		 *
		 * <p> Returns {@link ChatInviteLink ChatInviteLink} </p>
		**/
		public ReplacePrimaryChatInviteLink(long chatId) {
			this.chatId = chatId;
		}

		/**
		 * Replaces current primary invite link for a chat with a new primary invite link. Available for basic groups, supergroups, and channels. Requires administrator privileges and canInviteUsers right.
		 *
		 * <p> Returns {@link ChatInviteLink ChatInviteLink} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ReplacePrimaryChatInviteLink(DataInput input) throws IOException {
			this.chatId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ReplacePrimaryChatInviteLink.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ReplacePrimaryChatInviteLink.CONSTRUCTOR);
			output.writeLong(this.chatId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ReplacePrimaryChatInviteLink replacePrimaryChatInviteLink = (ReplacePrimaryChatInviteLink) o;
			if (this.chatId != replacePrimaryChatInviteLink.chatId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.chatId);
		}
	}

	/**
	 * Replaces the current RTMP URL for streaming to the chat; requires
	 * creator privileges.
	 * <p> Returns {@link RtmpUrl RtmpUrl} </p>
	**/
	public static final class ReplaceVideoChatRtmpUrl extends Function<RtmpUrl> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 558862304;

		/**
		 * Replaces the current RTMP URL for streaming to the chat; requires creator privileges.
		 *
		 * <p> Returns {@link RtmpUrl RtmpUrl} </p>
		**/
		public ReplaceVideoChatRtmpUrl() {}

		/**
		 * Replaces the current RTMP URL for streaming to the chat; requires creator privileges.
		 *
		 * <p> Returns {@link RtmpUrl RtmpUrl} </p>
		 *
		 * @param chatId Chat identifier.
		 *
		 * <p> Returns {@link RtmpUrl RtmpUrl} </p>
		**/
		public ReplaceVideoChatRtmpUrl(long chatId) {
			this.chatId = chatId;
		}

		/**
		 * Replaces the current RTMP URL for streaming to the chat; requires creator privileges.
		 *
		 * <p> Returns {@link RtmpUrl RtmpUrl} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ReplaceVideoChatRtmpUrl(DataInput input) throws IOException {
			this.chatId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ReplaceVideoChatRtmpUrl.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ReplaceVideoChatRtmpUrl.CONSTRUCTOR);
			output.writeLong(this.chatId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ReplaceVideoChatRtmpUrl replaceVideoChatRtmpUrl = (ReplaceVideoChatRtmpUrl) o;
			if (this.chatId != replaceVideoChatRtmpUrl.chatId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.chatId);
		}
	}

	/**
	 * Reports a chat to the Telegram moderators. A chat can be reported
	 * only from the chat action bar, or if chat.canBeReported.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ReportChat extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Identifiers of reported messages; may be empty to report the whole chat.
		**/
		public long[] messageIds;

		/**
		 * The reason for reporting the chat.
		**/
		public ChatReportReason reason;

		/**
		 * Additional report details; 0-1024 characters.
		**/
		public String text;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -964543587;

		/**
		 * Reports a chat to the Telegram moderators. A chat can be reported only from the chat action bar, or if chat.canBeReported.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ReportChat() {}

		/**
		 * Reports a chat to the Telegram moderators. A chat can be reported only from the chat action bar, or if chat.canBeReported.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param messageIds Identifiers of reported messages; may be empty to report the whole chat.
		 * @param reason The reason for reporting the chat.
		 * @param text Additional report details; 0-1024 characters.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ReportChat(long chatId,
				long[] messageIds,
				ChatReportReason reason,
				String text) {
			this.chatId = chatId;
			this.messageIds = messageIds;
			this.reason = reason;
			this.text = text;
		}

		/**
		 * Reports a chat to the Telegram moderators. A chat can be reported only from the chat action bar, or if chat.canBeReported.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ReportChat(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				this.messageIds = new long[input.readInt()];
				for (int i = 0; i < this.messageIds.length; i++) {
					this.messageIds[i] = input.readLong();
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ChatReportReasonSpam.CONSTRUCTOR: this.reason = new ChatReportReasonSpam(input); break;
					case ChatReportReasonViolence.CONSTRUCTOR: this.reason = new ChatReportReasonViolence(input); break;
					case ChatReportReasonPornography.CONSTRUCTOR: this.reason = new ChatReportReasonPornography(input); break;
					case ChatReportReasonChildAbuse.CONSTRUCTOR: this.reason = new ChatReportReasonChildAbuse(input); break;
					case ChatReportReasonCopyright.CONSTRUCTOR: this.reason = new ChatReportReasonCopyright(input); break;
					case ChatReportReasonUnrelatedLocation.CONSTRUCTOR: this.reason = new ChatReportReasonUnrelatedLocation(input); break;
					case ChatReportReasonFake.CONSTRUCTOR: this.reason = new ChatReportReasonFake(input); break;
					case ChatReportReasonIllegalDrugs.CONSTRUCTOR: this.reason = new ChatReportReasonIllegalDrugs(input); break;
					case ChatReportReasonPersonalDetails.CONSTRUCTOR: this.reason = new ChatReportReasonPersonalDetails(input); break;
					case ChatReportReasonCustom.CONSTRUCTOR: this.reason = new ChatReportReasonCustom(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				byte[] textTmp = new byte[input.readInt()];
				input.readFully(textTmp);
				this.text = new String(textTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ReportChat.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ReportChat.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.messageIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.messageIds.length);
				for (int i = 0; i < this.messageIds.length; i++) {
					output.writeLong(this.messageIds[i]);
				}
			}
			if (this.reason == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.reason.serialize(output);
			}
			if (this.text == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] textTmp = this.text.getBytes(StandardCharsets.UTF_8);
				output.writeInt(textTmp.length);
				output.write(textTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ReportChat reportChat = (ReportChat) o;
			if (this.chatId != reportChat.chatId) {
				return false;
			}
			if (!Arrays.equals(this.messageIds, reportChat.messageIds)) {
				return false;
			}
			if (!Objects.equals(this.reason, reportChat.reason)) {
				return false;
			}
			if (this.text != reportChat.text) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (Arrays.hashCode(this.messageIds));
			result = result * 31 + (this.reason == null ? 0 : this.reason.hashCode());
			result = result * 31 + (this.text == null ? 0 : this.text.hashCode());
			return result;
		}
	}

	/**
	 * Reports a chat photo to the Telegram moderators. A chat photo can be
	 * reported only if chat.canBeReported.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ReportChatPhoto extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Identifier of the photo to report. Only full photos from chatPhoto can be reported.
		**/
		public int fileId;

		/**
		 * The reason for reporting the chat photo.
		**/
		public ChatReportReason reason;

		/**
		 * Additional report details; 0-1024 characters.
		**/
		public String text;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 734652708;

		/**
		 * Reports a chat photo to the Telegram moderators. A chat photo can be reported only if chat.canBeReported.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ReportChatPhoto() {}

		/**
		 * Reports a chat photo to the Telegram moderators. A chat photo can be reported only if chat.canBeReported.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param fileId Identifier of the photo to report. Only full photos from chatPhoto can be reported.
		 * @param reason The reason for reporting the chat photo.
		 * @param text Additional report details; 0-1024 characters.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ReportChatPhoto(long chatId,
				int fileId,
				ChatReportReason reason,
				String text) {
			this.chatId = chatId;
			this.fileId = fileId;
			this.reason = reason;
			this.text = text;
		}

		/**
		 * Reports a chat photo to the Telegram moderators. A chat photo can be reported only if chat.canBeReported.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ReportChatPhoto(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.fileId = input.readInt();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ChatReportReasonSpam.CONSTRUCTOR: this.reason = new ChatReportReasonSpam(input); break;
					case ChatReportReasonViolence.CONSTRUCTOR: this.reason = new ChatReportReasonViolence(input); break;
					case ChatReportReasonPornography.CONSTRUCTOR: this.reason = new ChatReportReasonPornography(input); break;
					case ChatReportReasonChildAbuse.CONSTRUCTOR: this.reason = new ChatReportReasonChildAbuse(input); break;
					case ChatReportReasonCopyright.CONSTRUCTOR: this.reason = new ChatReportReasonCopyright(input); break;
					case ChatReportReasonUnrelatedLocation.CONSTRUCTOR: this.reason = new ChatReportReasonUnrelatedLocation(input); break;
					case ChatReportReasonFake.CONSTRUCTOR: this.reason = new ChatReportReasonFake(input); break;
					case ChatReportReasonIllegalDrugs.CONSTRUCTOR: this.reason = new ChatReportReasonIllegalDrugs(input); break;
					case ChatReportReasonPersonalDetails.CONSTRUCTOR: this.reason = new ChatReportReasonPersonalDetails(input); break;
					case ChatReportReasonCustom.CONSTRUCTOR: this.reason = new ChatReportReasonCustom(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				byte[] textTmp = new byte[input.readInt()];
				input.readFully(textTmp);
				this.text = new String(textTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ReportChatPhoto.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ReportChatPhoto.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeInt(this.fileId);
			if (this.reason == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.reason.serialize(output);
			}
			if (this.text == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] textTmp = this.text.getBytes(StandardCharsets.UTF_8);
				output.writeInt(textTmp.length);
				output.write(textTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ReportChatPhoto reportChatPhoto = (ReportChatPhoto) o;
			if (this.chatId != reportChatPhoto.chatId) {
				return false;
			}
			if (this.fileId != reportChatPhoto.fileId) {
				return false;
			}
			if (!Objects.equals(this.reason, reportChatPhoto.reason)) {
				return false;
			}
			if (this.text != reportChatPhoto.text) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.reason == null ? 0 : this.reason.hashCode());
			result = result * 31 + (this.text == null ? 0 : this.text.hashCode());
			return result;
		}
	}

	/**
	 * Reports reactions set on a message to the Telegram moderators.
	 * Reactions on a message can be reported only if
	 * message.canReportReactions.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ReportMessageReactions extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Message identifier.
		**/
		public long messageId;

		/**
		 * Identifier of the sender, which added the reaction.
		**/
		public MessageSender senderId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 919111719;

		/**
		 * Reports reactions set on a message to the Telegram moderators. Reactions on a message can be reported only if message.canReportReactions.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ReportMessageReactions() {}

		/**
		 * Reports reactions set on a message to the Telegram moderators. Reactions on a message can be reported only if message.canReportReactions.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param messageId Message identifier.
		 * @param senderId Identifier of the sender, which added the reaction.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ReportMessageReactions(long chatId, long messageId, MessageSender senderId) {
			this.chatId = chatId;
			this.messageId = messageId;
			this.senderId = senderId;
		}

		/**
		 * Reports reactions set on a message to the Telegram moderators. Reactions on a message can be reported only if message.canReportReactions.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ReportMessageReactions(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case MessageSenderUser.CONSTRUCTOR: this.senderId = new MessageSenderUser(input); break;
					case MessageSenderChat.CONSTRUCTOR: this.senderId = new MessageSenderChat(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ReportMessageReactions.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ReportMessageReactions.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
			if (this.senderId == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.senderId.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ReportMessageReactions reportMessageReactions = (ReportMessageReactions) o;
			if (this.chatId != reportMessageReactions.chatId) {
				return false;
			}
			if (this.messageId != reportMessageReactions.messageId) {
				return false;
			}
			if (!Objects.equals(this.senderId, reportMessageReactions.senderId)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.senderId == null ? 0 : this.senderId.hashCode());
			return result;
		}
	}

	/**
	 * Reports a false deletion of a message by aggressive anti-spam checks;
	 * requires administrator rights in the supergroup. Can be called only
	 * for messages from chatEventMessageDeleted with
	 * canReportAntiSpamFalsePositive == true.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ReportSupergroupAntiSpamFalsePositive extends Function<Ok> {


		/**
		 * Supergroup identifier.
		**/
		public long supergroupId;

		/**
		 * Identifier of the erroneously deleted message.
		**/
		public long messageId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -516050872;

		/**
		 * Reports a false deletion of a message by aggressive anti-spam checks; requires administrator rights in the supergroup. Can be called only for messages from chatEventMessageDeleted with canReportAntiSpamFalsePositive == true.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ReportSupergroupAntiSpamFalsePositive() {}

		/**
		 * Reports a false deletion of a message by aggressive anti-spam checks; requires administrator rights in the supergroup. Can be called only for messages from chatEventMessageDeleted with canReportAntiSpamFalsePositive == true.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param supergroupId Supergroup identifier.
		 * @param messageId Identifier of the erroneously deleted message.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ReportSupergroupAntiSpamFalsePositive(long supergroupId, long messageId) {
			this.supergroupId = supergroupId;
			this.messageId = messageId;
		}

		/**
		 * Reports a false deletion of a message by aggressive anti-spam checks; requires administrator rights in the supergroup. Can be called only for messages from chatEventMessageDeleted with canReportAntiSpamFalsePositive == true.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ReportSupergroupAntiSpamFalsePositive(DataInput input) throws IOException {
			this.supergroupId = input.readLong();
			this.messageId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ReportSupergroupAntiSpamFalsePositive.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ReportSupergroupAntiSpamFalsePositive.CONSTRUCTOR);
			output.writeLong(this.supergroupId);
			output.writeLong(this.messageId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ReportSupergroupAntiSpamFalsePositive reportSupergroupAntiSpamFalsePositive = (ReportSupergroupAntiSpamFalsePositive) o;
			if (this.supergroupId != reportSupergroupAntiSpamFalsePositive.supergroupId) {
				return false;
			}
			if (this.messageId != reportSupergroupAntiSpamFalsePositive.messageId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.supergroupId);
			return result;
		}
	}

	/**
	 * Reports messages in a supergroup as spam; requires administrator
	 * rights in the supergroup.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ReportSupergroupSpam extends Function<Ok> {


		/**
		 * Supergroup identifier.
		**/
		public long supergroupId;

		/**
		 * Identifiers of messages to report.
		**/
		public long[] messageIds;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -94825000;

		/**
		 * Reports messages in a supergroup as spam; requires administrator rights in the supergroup.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ReportSupergroupSpam() {}

		/**
		 * Reports messages in a supergroup as spam; requires administrator rights in the supergroup.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param supergroupId Supergroup identifier.
		 * @param messageIds Identifiers of messages to report.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ReportSupergroupSpam(long supergroupId, long[] messageIds) {
			this.supergroupId = supergroupId;
			this.messageIds = messageIds;
		}

		/**
		 * Reports messages in a supergroup as spam; requires administrator rights in the supergroup.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ReportSupergroupSpam(DataInput input) throws IOException {
			this.supergroupId = input.readLong();
			if (input.readBoolean()) {
				this.messageIds = new long[input.readInt()];
				for (int i = 0; i < this.messageIds.length; i++) {
					this.messageIds[i] = input.readLong();
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ReportSupergroupSpam.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ReportSupergroupSpam.CONSTRUCTOR);
			output.writeLong(this.supergroupId);
			if (this.messageIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.messageIds.length);
				for (int i = 0; i < this.messageIds.length; i++) {
					output.writeLong(this.messageIds[i]);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ReportSupergroupSpam reportSupergroupSpam = (ReportSupergroupSpam) o;
			if (this.supergroupId != reportSupergroupSpam.supergroupId) {
				return false;
			}
			if (!Arrays.equals(this.messageIds, reportSupergroupSpam.messageIds)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.supergroupId);
			result = result * 31 + (Arrays.hashCode(this.messageIds));
			return result;
		}
	}

	/**
	 * Requests to send a 2-step verification password recovery code to an
	 * email address that was previously set up. Works only when the current
	 * authorization state is authorizationStateWaitPassword.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class RequestAuthenticationPasswordRecovery extends Function<Ok> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1393896118;

		/**
		 * Requests to send a 2-step verification password recovery code to an email address that was previously set up. Works only when the current authorization state is authorizationStateWaitPassword.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public RequestAuthenticationPasswordRecovery() {}

		/**
		 * Requests to send a 2-step verification password recovery code to an email address that was previously set up. Works only when the current authorization state is authorizationStateWaitPassword.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/

		/**
		 * Requests to send a 2-step verification password recovery code to an email address that was previously set up. Works only when the current authorization state is authorizationStateWaitPassword.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RequestAuthenticationPasswordRecovery(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RequestAuthenticationPasswordRecovery.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RequestAuthenticationPasswordRecovery.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return RequestAuthenticationPasswordRecovery.CONSTRUCTOR;
		}
	}

	/**
	 * Requests to send a 2-step verification password recovery code to an
	 * email address that was previously set up.
	 * <p> Returns {@link EmailAddressAuthenticationCodeInfo
	 * EmailAddressAuthenticationCodeInfo} </p>
	**/
	public static final class RequestPasswordRecovery extends Function<EmailAddressAuthenticationCodeInfo> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -13777582;

		/**
		 * Requests to send a 2-step verification password recovery code to an email address that was previously set up.
		 *
		 * <p> Returns {@link EmailAddressAuthenticationCodeInfo EmailAddressAuthenticationCodeInfo} </p>
		**/
		public RequestPasswordRecovery() {}

		/**
		 * Requests to send a 2-step verification password recovery code to an email address that was previously set up.
		 *
		 * <p> Returns {@link EmailAddressAuthenticationCodeInfo EmailAddressAuthenticationCodeInfo} </p>
		 *
		 *
		 * <p> Returns {@link EmailAddressAuthenticationCodeInfo EmailAddressAuthenticationCodeInfo} </p>
		**/

		/**
		 * Requests to send a 2-step verification password recovery code to an email address that was previously set up.
		 *
		 * <p> Returns {@link EmailAddressAuthenticationCodeInfo EmailAddressAuthenticationCodeInfo} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RequestPasswordRecovery(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RequestPasswordRecovery.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RequestPasswordRecovery.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return RequestPasswordRecovery.CONSTRUCTOR;
		}
	}

	/**
	 * Requests QR code authentication by scanning a QR code on another
	 * logged in device. Works only when the current authorization state is
	 * authorizationStateWaitPhoneNumber, or if there is no pending
	 * authentication query and the current authorization state is
	 * authorizationStateWaitEmailAddress, authorizationStateWaitEmailCode,
	 * authorizationStateWaitCode, authorizationStateWaitRegistration, or
	 * authorizationStateWaitPassword.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class RequestQrCodeAuthentication extends Function<Ok> {


		/**
		 * List of user identifiers of other users currently using the application.
		**/
		public long[] otherUserIds;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1363496527;

		/**
		 * Requests QR code authentication by scanning a QR code on another logged in device. Works only when the current authorization state is authorizationStateWaitPhoneNumber, or if there is no pending authentication query and the current authorization state is authorizationStateWaitEmailAddress, authorizationStateWaitEmailCode, authorizationStateWaitCode, authorizationStateWaitRegistration, or authorizationStateWaitPassword.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public RequestQrCodeAuthentication() {}

		/**
		 * Requests QR code authentication by scanning a QR code on another logged in device. Works only when the current authorization state is authorizationStateWaitPhoneNumber, or if there is no pending authentication query and the current authorization state is authorizationStateWaitEmailAddress, authorizationStateWaitEmailCode, authorizationStateWaitCode, authorizationStateWaitRegistration, or authorizationStateWaitPassword.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param otherUserIds List of user identifiers of other users currently using the application.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public RequestQrCodeAuthentication(long[] otherUserIds) {
			this.otherUserIds = otherUserIds;
		}

		/**
		 * Requests QR code authentication by scanning a QR code on another logged in device. Works only when the current authorization state is authorizationStateWaitPhoneNumber, or if there is no pending authentication query and the current authorization state is authorizationStateWaitEmailAddress, authorizationStateWaitEmailCode, authorizationStateWaitCode, authorizationStateWaitRegistration, or authorizationStateWaitPassword.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RequestQrCodeAuthentication(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.otherUserIds = new long[input.readInt()];
				for (int i = 0; i < this.otherUserIds.length; i++) {
					this.otherUserIds[i] = input.readLong();
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RequestQrCodeAuthentication.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RequestQrCodeAuthentication.CONSTRUCTOR);
			if (this.otherUserIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.otherUserIds.length);
				for (int i = 0; i < this.otherUserIds.length; i++) {
					output.writeLong(this.otherUserIds[i]);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			RequestQrCodeAuthentication requestQrCodeAuthentication = (RequestQrCodeAuthentication) o;
			if (!Arrays.equals(this.otherUserIds, requestQrCodeAuthentication.otherUserIds)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.otherUserIds);
		}
	}

	/**
	 * Resends an authentication code to the user. Works only when the
	 * current authorization state is authorizationStateWaitCode, the
	 * nextCodeType of the result is not null and the server-specified
	 * timeout has passed, or when the current authorization state is
	 * authorizationStateWaitEmailCode.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ResendAuthenticationCode extends Function<Ok> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -814377191;

		/**
		 * Resends an authentication code to the user. Works only when the current authorization state is authorizationStateWaitCode, the nextCodeType of the result is not null and the server-specified timeout has passed, or when the current authorization state is authorizationStateWaitEmailCode.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ResendAuthenticationCode() {}

		/**
		 * Resends an authentication code to the user. Works only when the current authorization state is authorizationStateWaitCode, the nextCodeType of the result is not null and the server-specified timeout has passed, or when the current authorization state is authorizationStateWaitEmailCode.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/

		/**
		 * Resends an authentication code to the user. Works only when the current authorization state is authorizationStateWaitCode, the nextCodeType of the result is not null and the server-specified timeout has passed, or when the current authorization state is authorizationStateWaitEmailCode.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ResendAuthenticationCode(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ResendAuthenticationCode.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ResendAuthenticationCode.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ResendAuthenticationCode.CONSTRUCTOR;
		}
	}

	/**
	 * Resends the authentication code sent to confirm a new phone number
	 * for the current user. Works only if the previously received
	 * authenticationCodeInfo nextCodeType was not null and the
	 * server-specified timeout has passed.
	 * <p> Returns {@link AuthenticationCodeInfo AuthenticationCodeInfo} </p>
	**/
	public static final class ResendChangePhoneNumberCode extends Function<AuthenticationCodeInfo> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -786772060;

		/**
		 * Resends the authentication code sent to confirm a new phone number for the current user. Works only if the previously received authenticationCodeInfo nextCodeType was not null and the server-specified timeout has passed.
		 *
		 * <p> Returns {@link AuthenticationCodeInfo AuthenticationCodeInfo} </p>
		**/
		public ResendChangePhoneNumberCode() {}

		/**
		 * Resends the authentication code sent to confirm a new phone number for the current user. Works only if the previously received authenticationCodeInfo nextCodeType was not null and the server-specified timeout has passed.
		 *
		 * <p> Returns {@link AuthenticationCodeInfo AuthenticationCodeInfo} </p>
		 *
		 *
		 * <p> Returns {@link AuthenticationCodeInfo AuthenticationCodeInfo} </p>
		**/

		/**
		 * Resends the authentication code sent to confirm a new phone number for the current user. Works only if the previously received authenticationCodeInfo nextCodeType was not null and the server-specified timeout has passed.
		 *
		 * <p> Returns {@link AuthenticationCodeInfo AuthenticationCodeInfo} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ResendChangePhoneNumberCode(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ResendChangePhoneNumberCode.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ResendChangePhoneNumberCode.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ResendChangePhoneNumberCode.CONSTRUCTOR;
		}
	}

	/**
	 * Resends the code to verify an email address to be added to a
	 * user&#039;s Telegram Passport.
	 * <p> Returns {@link EmailAddressAuthenticationCodeInfo
	 * EmailAddressAuthenticationCodeInfo} </p>
	**/
	public static final class ResendEmailAddressVerificationCode extends Function<EmailAddressAuthenticationCodeInfo> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1872416732;

		/**
		 * Resends the code to verify an email address to be added to a user&#039;s Telegram Passport.
		 *
		 * <p> Returns {@link EmailAddressAuthenticationCodeInfo EmailAddressAuthenticationCodeInfo} </p>
		**/
		public ResendEmailAddressVerificationCode() {}

		/**
		 * Resends the code to verify an email address to be added to a user&#039;s Telegram Passport.
		 *
		 * <p> Returns {@link EmailAddressAuthenticationCodeInfo EmailAddressAuthenticationCodeInfo} </p>
		 *
		 *
		 * <p> Returns {@link EmailAddressAuthenticationCodeInfo EmailAddressAuthenticationCodeInfo} </p>
		**/

		/**
		 * Resends the code to verify an email address to be added to a user&#039;s Telegram Passport.
		 *
		 * <p> Returns {@link EmailAddressAuthenticationCodeInfo EmailAddressAuthenticationCodeInfo} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ResendEmailAddressVerificationCode(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ResendEmailAddressVerificationCode.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ResendEmailAddressVerificationCode.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ResendEmailAddressVerificationCode.CONSTRUCTOR;
		}
	}

	/**
	 * Resends the login email address verification code.
	 * <p> Returns {@link EmailAddressAuthenticationCodeInfo
	 * EmailAddressAuthenticationCodeInfo} </p>
	**/
	public static final class ResendLoginEmailAddressCode extends Function<EmailAddressAuthenticationCodeInfo> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 292966933;

		/**
		 * Resends the login email address verification code.
		 *
		 * <p> Returns {@link EmailAddressAuthenticationCodeInfo EmailAddressAuthenticationCodeInfo} </p>
		**/
		public ResendLoginEmailAddressCode() {}

		/**
		 * Resends the login email address verification code.
		 *
		 * <p> Returns {@link EmailAddressAuthenticationCodeInfo EmailAddressAuthenticationCodeInfo} </p>
		 *
		 *
		 * <p> Returns {@link EmailAddressAuthenticationCodeInfo EmailAddressAuthenticationCodeInfo} </p>
		**/

		/**
		 * Resends the login email address verification code.
		 *
		 * <p> Returns {@link EmailAddressAuthenticationCodeInfo EmailAddressAuthenticationCodeInfo} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ResendLoginEmailAddressCode(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ResendLoginEmailAddressCode.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ResendLoginEmailAddressCode.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ResendLoginEmailAddressCode.CONSTRUCTOR;
		}
	}

	/**
	 * Resends messages which failed to send. Can be called only for
	 * messages for which messageSendingStateFailed.canRetry is true and
	 * after specified in messageSendingStateFailed.retryAfter time passed.
	 * If a message is re-sent, the corresponding failed to send message is
	 * deleted. Returns the sent messages in the same order as the message
	 * identifiers passed in messageIds. If a message can&#039;t be re-sent,
	 * null will be returned instead of the message.
	 * <p> Returns {@link Messages Messages} </p>
	**/
	public static final class ResendMessages extends Function<Messages> {


		/**
		 * Identifier of the chat to send messages.
		**/
		public long chatId;

		/**
		 * Identifiers of the messages to resend. Message identifiers must be in a strictly increasing order.
		**/
		public long[] messageIds;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -940655817;

		/**
		 * Resends messages which failed to send. Can be called only for messages for which messageSendingStateFailed.canRetry is true and after specified in messageSendingStateFailed.retryAfter time passed. If a message is re-sent, the corresponding failed to send message is deleted. Returns the sent messages in the same order as the message identifiers passed in messageIds. If a message can&#039;t be re-sent, null will be returned instead of the message.
		 *
		 * <p> Returns {@link Messages Messages} </p>
		**/
		public ResendMessages() {}

		/**
		 * Resends messages which failed to send. Can be called only for messages for which messageSendingStateFailed.canRetry is true and after specified in messageSendingStateFailed.retryAfter time passed. If a message is re-sent, the corresponding failed to send message is deleted. Returns the sent messages in the same order as the message identifiers passed in messageIds. If a message can&#039;t be re-sent, null will be returned instead of the message.
		 *
		 * <p> Returns {@link Messages Messages} </p>
		 *
		 * @param chatId Identifier of the chat to send messages.
		 * @param messageIds Identifiers of the messages to resend. Message identifiers must be in a strictly increasing order.
		 *
		 * <p> Returns {@link Messages Messages} </p>
		**/
		public ResendMessages(long chatId, long[] messageIds) {
			this.chatId = chatId;
			this.messageIds = messageIds;
		}

		/**
		 * Resends messages which failed to send. Can be called only for messages for which messageSendingStateFailed.canRetry is true and after specified in messageSendingStateFailed.retryAfter time passed. If a message is re-sent, the corresponding failed to send message is deleted. Returns the sent messages in the same order as the message identifiers passed in messageIds. If a message can&#039;t be re-sent, null will be returned instead of the message.
		 *
		 * <p> Returns {@link Messages Messages} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ResendMessages(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				this.messageIds = new long[input.readInt()];
				for (int i = 0; i < this.messageIds.length; i++) {
					this.messageIds[i] = input.readLong();
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ResendMessages.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ResendMessages.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.messageIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.messageIds.length);
				for (int i = 0; i < this.messageIds.length; i++) {
					output.writeLong(this.messageIds[i]);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ResendMessages resendMessages = (ResendMessages) o;
			if (this.chatId != resendMessages.chatId) {
				return false;
			}
			if (!Arrays.equals(this.messageIds, resendMessages.messageIds)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (Arrays.hashCode(this.messageIds));
			return result;
		}
	}

	/**
	 * Resends phone number confirmation code.
	 * <p> Returns {@link AuthenticationCodeInfo AuthenticationCodeInfo} </p>
	**/
	public static final class ResendPhoneNumberConfirmationCode extends Function<AuthenticationCodeInfo> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2069068522;

		/**
		 * Resends phone number confirmation code.
		 *
		 * <p> Returns {@link AuthenticationCodeInfo AuthenticationCodeInfo} </p>
		**/
		public ResendPhoneNumberConfirmationCode() {}

		/**
		 * Resends phone number confirmation code.
		 *
		 * <p> Returns {@link AuthenticationCodeInfo AuthenticationCodeInfo} </p>
		 *
		 *
		 * <p> Returns {@link AuthenticationCodeInfo AuthenticationCodeInfo} </p>
		**/

		/**
		 * Resends phone number confirmation code.
		 *
		 * <p> Returns {@link AuthenticationCodeInfo AuthenticationCodeInfo} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ResendPhoneNumberConfirmationCode(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ResendPhoneNumberConfirmationCode.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ResendPhoneNumberConfirmationCode.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ResendPhoneNumberConfirmationCode.CONSTRUCTOR;
		}
	}

	/**
	 * Resends the code to verify a phone number to be added to a
	 * user&#039;s Telegram Passport.
	 * <p> Returns {@link AuthenticationCodeInfo AuthenticationCodeInfo} </p>
	**/
	public static final class ResendPhoneNumberVerificationCode extends Function<AuthenticationCodeInfo> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1367629820;

		/**
		 * Resends the code to verify a phone number to be added to a user&#039;s Telegram Passport.
		 *
		 * <p> Returns {@link AuthenticationCodeInfo AuthenticationCodeInfo} </p>
		**/
		public ResendPhoneNumberVerificationCode() {}

		/**
		 * Resends the code to verify a phone number to be added to a user&#039;s Telegram Passport.
		 *
		 * <p> Returns {@link AuthenticationCodeInfo AuthenticationCodeInfo} </p>
		 *
		 *
		 * <p> Returns {@link AuthenticationCodeInfo AuthenticationCodeInfo} </p>
		**/

		/**
		 * Resends the code to verify a phone number to be added to a user&#039;s Telegram Passport.
		 *
		 * <p> Returns {@link AuthenticationCodeInfo AuthenticationCodeInfo} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ResendPhoneNumberVerificationCode(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ResendPhoneNumberVerificationCode.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ResendPhoneNumberVerificationCode.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ResendPhoneNumberVerificationCode.CONSTRUCTOR;
		}
	}

	/**
	 * Resends the 2-step verification recovery email address verification
	 * code.
	 * <p> Returns {@link PasswordState PasswordState} </p>
	**/
	public static final class ResendRecoveryEmailAddressCode extends Function<PasswordState> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 433483548;

		/**
		 * Resends the 2-step verification recovery email address verification code.
		 *
		 * <p> Returns {@link PasswordState PasswordState} </p>
		**/
		public ResendRecoveryEmailAddressCode() {}

		/**
		 * Resends the 2-step verification recovery email address verification code.
		 *
		 * <p> Returns {@link PasswordState PasswordState} </p>
		 *
		 *
		 * <p> Returns {@link PasswordState PasswordState} </p>
		**/

		/**
		 * Resends the 2-step verification recovery email address verification code.
		 *
		 * <p> Returns {@link PasswordState PasswordState} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ResendRecoveryEmailAddressCode(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ResendRecoveryEmailAddressCode.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ResendRecoveryEmailAddressCode.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ResendRecoveryEmailAddressCode.CONSTRUCTOR;
		}
	}

	/**
	 * Resets all notification settings to their default values. By default,
	 * all chats are unmuted and message previews are shown.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ResetAllNotificationSettings extends Function<Ok> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -174020359;

		/**
		 * Resets all notification settings to their default values. By default, all chats are unmuted and message previews are shown.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ResetAllNotificationSettings() {}

		/**
		 * Resets all notification settings to their default values. By default, all chats are unmuted and message previews are shown.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/

		/**
		 * Resets all notification settings to their default values. By default, all chats are unmuted and message previews are shown.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ResetAllNotificationSettings(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ResetAllNotificationSettings.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ResetAllNotificationSettings.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ResetAllNotificationSettings.CONSTRUCTOR;
		}
	}

	/**
	 * Resets the login email address. May return an error with a message
	 * &quot;TASK_ALREADY_EXISTS&quot; if reset is still pending. Works only
	 * when the current authorization state is
	 * authorizationStateWaitEmailCode and
	 * authorizationState.canResetEmailAddress == true.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ResetAuthenticationEmailAddress extends Function<Ok> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -415075796;

		/**
		 * Resets the login email address. May return an error with a message &quot;TASK_ALREADY_EXISTS&quot; if reset is still pending. Works only when the current authorization state is authorizationStateWaitEmailCode and authorizationState.canResetEmailAddress == true.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ResetAuthenticationEmailAddress() {}

		/**
		 * Resets the login email address. May return an error with a message &quot;TASK_ALREADY_EXISTS&quot; if reset is still pending. Works only when the current authorization state is authorizationStateWaitEmailCode and authorizationState.canResetEmailAddress == true.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/

		/**
		 * Resets the login email address. May return an error with a message &quot;TASK_ALREADY_EXISTS&quot; if reset is still pending. Works only when the current authorization state is authorizationStateWaitEmailCode and authorizationState.canResetEmailAddress == true.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ResetAuthenticationEmailAddress(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ResetAuthenticationEmailAddress.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ResetAuthenticationEmailAddress.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ResetAuthenticationEmailAddress.CONSTRUCTOR;
		}
	}

	/**
	 * Resets list of installed backgrounds to its default value.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ResetBackgrounds extends Function<Ok> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 204852088;

		/**
		 * Resets list of installed backgrounds to its default value.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ResetBackgrounds() {}

		/**
		 * Resets list of installed backgrounds to its default value.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/

		/**
		 * Resets list of installed backgrounds to its default value.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ResetBackgrounds(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ResetBackgrounds.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ResetBackgrounds.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ResetBackgrounds.CONSTRUCTOR;
		}
	}

	/**
	 * Resets all network data usage statistics to zero. Can be called
	 * before authorization.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ResetNetworkStatistics extends Function<Ok> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1646452102;

		/**
		 * Resets all network data usage statistics to zero. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ResetNetworkStatistics() {}

		/**
		 * Resets all network data usage statistics to zero. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/

		/**
		 * Resets all network data usage statistics to zero. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ResetNetworkStatistics(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ResetNetworkStatistics.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ResetNetworkStatistics.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ResetNetworkStatistics.CONSTRUCTOR;
		}
	}

	/**
	 * Removes 2-step verification password without previous password and
	 * access to recovery email address. The password can&#039;t be reset
	 * immediately and the request needs to be repeated after the specified
	 * time.
	 * <p> Returns {@link ResetPasswordResult ResetPasswordResult} </p>
	**/
	public static final class ResetPassword extends Function<ResetPasswordResult> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -593589091;

		/**
		 * Removes 2-step verification password without previous password and access to recovery email address. The password can&#039;t be reset immediately and the request needs to be repeated after the specified time.
		 *
		 * <p> Returns {@link ResetPasswordResult ResetPasswordResult} </p>
		**/
		public ResetPassword() {}

		/**
		 * Removes 2-step verification password without previous password and access to recovery email address. The password can&#039;t be reset immediately and the request needs to be repeated after the specified time.
		 *
		 * <p> Returns {@link ResetPasswordResult ResetPasswordResult} </p>
		 *
		 *
		 * <p> Returns {@link ResetPasswordResult ResetPasswordResult} </p>
		**/

		/**
		 * Removes 2-step verification password without previous password and access to recovery email address. The password can&#039;t be reset immediately and the request needs to be repeated after the specified time.
		 *
		 * <p> Returns {@link ResetPasswordResult ResetPasswordResult} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ResetPassword(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ResetPassword.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ResetPassword.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return ResetPassword.CONSTRUCTOR;
		}
	}

	/**
	 * Revokes invite link for a chat. Available for basic groups,
	 * supergroups, and channels. Requires administrator privileges and
	 * canInviteUsers right in the chat for own links and owner privileges
	 * for other links. If a primary link is revoked, then additionally to
	 * the revoked link returns new primary link.
	 * <p> Returns {@link ChatInviteLinks ChatInviteLinks} </p>
	**/
	public static final class RevokeChatInviteLink extends Function<ChatInviteLinks> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Invite link to be revoked.
		**/
		public String inviteLink;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -776514135;

		/**
		 * Revokes invite link for a chat. Available for basic groups, supergroups, and channels. Requires administrator privileges and canInviteUsers right in the chat for own links and owner privileges for other links. If a primary link is revoked, then additionally to the revoked link returns new primary link.
		 *
		 * <p> Returns {@link ChatInviteLinks ChatInviteLinks} </p>
		**/
		public RevokeChatInviteLink() {}

		/**
		 * Revokes invite link for a chat. Available for basic groups, supergroups, and channels. Requires administrator privileges and canInviteUsers right in the chat for own links and owner privileges for other links. If a primary link is revoked, then additionally to the revoked link returns new primary link.
		 *
		 * <p> Returns {@link ChatInviteLinks ChatInviteLinks} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param inviteLink Invite link to be revoked.
		 *
		 * <p> Returns {@link ChatInviteLinks ChatInviteLinks} </p>
		**/
		public RevokeChatInviteLink(long chatId, String inviteLink) {
			this.chatId = chatId;
			this.inviteLink = inviteLink;
		}

		/**
		 * Revokes invite link for a chat. Available for basic groups, supergroups, and channels. Requires administrator privileges and canInviteUsers right in the chat for own links and owner privileges for other links. If a primary link is revoked, then additionally to the revoked link returns new primary link.
		 *
		 * <p> Returns {@link ChatInviteLinks ChatInviteLinks} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RevokeChatInviteLink(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				byte[] inviteLinkTmp = new byte[input.readInt()];
				input.readFully(inviteLinkTmp);
				this.inviteLink = new String(inviteLinkTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RevokeChatInviteLink.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RevokeChatInviteLink.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.inviteLink == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] inviteLinkTmp = this.inviteLink.getBytes(StandardCharsets.UTF_8);
				output.writeInt(inviteLinkTmp.length);
				output.write(inviteLinkTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			RevokeChatInviteLink revokeChatInviteLink = (RevokeChatInviteLink) o;
			if (this.chatId != revokeChatInviteLink.chatId) {
				return false;
			}
			if (this.inviteLink != revokeChatInviteLink.inviteLink) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.inviteLink == null ? 0 : this.inviteLink.hashCode());
			return result;
		}
	}

	/**
	 * Revokes invite link for a group call. Requires groupCall.canBeManaged
	 * group call flag.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class RevokeGroupCallInviteLink extends Function<Ok> {


		/**
		 * Group call identifier.
		**/
		public int groupCallId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 501589140;

		/**
		 * Revokes invite link for a group call. Requires groupCall.canBeManaged group call flag.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public RevokeGroupCallInviteLink() {}

		/**
		 * Revokes invite link for a group call. Requires groupCall.canBeManaged group call flag.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param groupCallId Group call identifier.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public RevokeGroupCallInviteLink(int groupCallId) {
			this.groupCallId = groupCallId;
		}

		/**
		 * Revokes invite link for a group call. Requires groupCall.canBeManaged group call flag.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public RevokeGroupCallInviteLink(DataInput input) throws IOException {
			this.groupCallId = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return RevokeGroupCallInviteLink.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(RevokeGroupCallInviteLink.CONSTRUCTOR);
			output.writeInt(this.groupCallId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			RevokeGroupCallInviteLink revokeGroupCallInviteLink = (RevokeGroupCallInviteLink) o;
			if (this.groupCallId != revokeGroupCallInviteLink.groupCallId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.groupCallId);
		}
	}

	/**
	 * Saves application log event on the server. Can be called before
	 * authorization.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SaveApplicationLogEvent extends Function<Ok> {


		/**
		 * Event type.
		**/
		public String type;

		/**
		 * Optional chat identifier, associated with the event.
		**/
		public long chatId;

		/**
		 * The log event data.
		**/
		public JsonValue data;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -811154930;

		/**
		 * Saves application log event on the server. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SaveApplicationLogEvent() {}

		/**
		 * Saves application log event on the server. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param type Event type.
		 * @param chatId Optional chat identifier, associated with the event.
		 * @param data The log event data.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SaveApplicationLogEvent(String type, long chatId, JsonValue data) {
			this.type = type;
			this.chatId = chatId;
			this.data = data;
		}

		/**
		 * Saves application log event on the server. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SaveApplicationLogEvent(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] typeTmp = new byte[input.readInt()];
				input.readFully(typeTmp);
				this.type = new String(typeTmp, StandardCharsets.UTF_8);
			}
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case JsonValueNull.CONSTRUCTOR: this.data = new JsonValueNull(input); break;
					case JsonValueBoolean.CONSTRUCTOR: this.data = new JsonValueBoolean(input); break;
					case JsonValueNumber.CONSTRUCTOR: this.data = new JsonValueNumber(input); break;
					case JsonValueString.CONSTRUCTOR: this.data = new JsonValueString(input); break;
					case JsonValueArray.CONSTRUCTOR: this.data = new JsonValueArray(input); break;
					case JsonValueObject.CONSTRUCTOR: this.data = new JsonValueObject(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SaveApplicationLogEvent.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SaveApplicationLogEvent.CONSTRUCTOR);
			if (this.type == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] typeTmp = this.type.getBytes(StandardCharsets.UTF_8);
				output.writeInt(typeTmp.length);
				output.write(typeTmp);
			}
			output.writeLong(this.chatId);
			if (this.data == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.data.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SaveApplicationLogEvent saveApplicationLogEvent = (SaveApplicationLogEvent) o;
			if (this.type != saveApplicationLogEvent.type) {
				return false;
			}
			if (this.chatId != saveApplicationLogEvent.chatId) {
				return false;
			}
			if (!Objects.equals(this.data, saveApplicationLogEvent.data)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.type == null ? 0 : this.type.hashCode());
			result = result * 31 + (this.data == null ? 0 : this.data.hashCode());
			return result;
		}
	}

	/**
	 * Searches for a background by its name.
	 * <p> Returns {@link Background Background} </p>
	**/
	public static final class SearchBackground extends Function<Background> {


		/**
		 * The name of the background.
		**/
		public String name;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2130996959;

		/**
		 * Searches for a background by its name.
		 *
		 * <p> Returns {@link Background Background} </p>
		**/
		public SearchBackground() {}

		/**
		 * Searches for a background by its name.
		 *
		 * <p> Returns {@link Background Background} </p>
		 *
		 * @param name The name of the background.
		 *
		 * <p> Returns {@link Background Background} </p>
		**/
		public SearchBackground(String name) {
			this.name = name;
		}

		/**
		 * Searches for a background by its name.
		 *
		 * <p> Returns {@link Background Background} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SearchBackground(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] nameTmp = new byte[input.readInt()];
				input.readFully(nameTmp);
				this.name = new String(nameTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SearchBackground.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SearchBackground.CONSTRUCTOR);
			if (this.name == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nameTmp = this.name.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nameTmp.length);
				output.write(nameTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SearchBackground searchBackground = (SearchBackground) o;
			if (this.name != searchBackground.name) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.name == null ? 0 : this.name.hashCode();
		}
	}

	/**
	 * Searches for call messages. Returns the results in reverse
	 * chronological order (i.e., in order of decreasing messageId). For
	 * optimal performance, the number of returned messages is chosen by
	 * TDLib.
	 * <p> Returns {@link FoundMessages FoundMessages} </p>
	**/
	public static final class SearchCallMessages extends Function<FoundMessages> {


		/**
		 * Offset of the first entry to return as received from the previous request; use empty string to get the first chunk of results.
		**/
		public String offset;

		/**
		 * The maximum number of messages to be returned; up to 100. For optimal performance, the number of returned messages is chosen by TDLib and can be smaller than the specified limit.
		**/
		public int limit;

		/**
		 * Pass true to search only for messages with missed/declined calls.
		**/
		public boolean onlyMissed;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1942229221;

		/**
		 * Searches for call messages. Returns the results in reverse chronological order (i.e., in order of decreasing messageId). For optimal performance, the number of returned messages is chosen by TDLib.
		 *
		 * <p> Returns {@link FoundMessages FoundMessages} </p>
		**/
		public SearchCallMessages() {}

		/**
		 * Searches for call messages. Returns the results in reverse chronological order (i.e., in order of decreasing messageId). For optimal performance, the number of returned messages is chosen by TDLib.
		 *
		 * <p> Returns {@link FoundMessages FoundMessages} </p>
		 *
		 * @param offset Offset of the first entry to return as received from the previous request; use empty string to get the first chunk of results.
		 * @param limit The maximum number of messages to be returned; up to 100. For optimal performance, the number of returned messages is chosen by TDLib and can be smaller than the specified limit.
		 * @param onlyMissed Pass true to search only for messages with missed/declined calls.
		 *
		 * <p> Returns {@link FoundMessages FoundMessages} </p>
		**/
		public SearchCallMessages(String offset, int limit, boolean onlyMissed) {
			this.offset = offset;
			this.limit = limit;
			this.onlyMissed = onlyMissed;
		}

		/**
		 * Searches for call messages. Returns the results in reverse chronological order (i.e., in order of decreasing messageId). For optimal performance, the number of returned messages is chosen by TDLib.
		 *
		 * <p> Returns {@link FoundMessages FoundMessages} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SearchCallMessages(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] offsetTmp = new byte[input.readInt()];
				input.readFully(offsetTmp);
				this.offset = new String(offsetTmp, StandardCharsets.UTF_8);
			}
			this.limit = input.readInt();
			this.onlyMissed = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SearchCallMessages.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SearchCallMessages.CONSTRUCTOR);
			if (this.offset == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] offsetTmp = this.offset.getBytes(StandardCharsets.UTF_8);
				output.writeInt(offsetTmp.length);
				output.write(offsetTmp);
			}
			output.writeInt(this.limit);
			output.writeBoolean(this.onlyMissed);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SearchCallMessages searchCallMessages = (SearchCallMessages) o;
			if (this.offset != searchCallMessages.offset) {
				return false;
			}
			if (this.limit != searchCallMessages.limit) {
				return false;
			}
			if (this.onlyMissed != searchCallMessages.onlyMissed) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.limit);
			result = result * 31 + (this.offset == null ? 0 : this.offset.hashCode());
			return result;
		}
	}

	/**
	 * Searches for a specified query in the first name, last name and
	 * usernames of the members of a specified chat. Requires administrator
	 * rights in channels.
	 * <p> Returns {@link ChatMembers ChatMembers} </p>
	**/
	public static final class SearchChatMembers extends Function<ChatMembers> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Query to search for.
		**/
		public String query;

		/**
		 * The maximum number of users to be returned; up to 200.
		**/
		public int limit;

		/**
		 * The type of users to search for; pass null to search among all chat members.
		**/
		public ChatMembersFilter filter;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -445823291;

		/**
		 * Searches for a specified query in the first name, last name and usernames of the members of a specified chat. Requires administrator rights in channels.
		 *
		 * <p> Returns {@link ChatMembers ChatMembers} </p>
		**/
		public SearchChatMembers() {}

		/**
		 * Searches for a specified query in the first name, last name and usernames of the members of a specified chat. Requires administrator rights in channels.
		 *
		 * <p> Returns {@link ChatMembers ChatMembers} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param query Query to search for.
		 * @param limit The maximum number of users to be returned; up to 200.
		 * @param filter The type of users to search for; pass null to search among all chat members.
		 *
		 * <p> Returns {@link ChatMembers ChatMembers} </p>
		**/
		public SearchChatMembers(long chatId,
				String query,
				int limit,
				ChatMembersFilter filter) {
			this.chatId = chatId;
			this.query = query;
			this.limit = limit;
			this.filter = filter;
		}

		/**
		 * Searches for a specified query in the first name, last name and usernames of the members of a specified chat. Requires administrator rights in channels.
		 *
		 * <p> Returns {@link ChatMembers ChatMembers} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SearchChatMembers(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				byte[] queryTmp = new byte[input.readInt()];
				input.readFully(queryTmp);
				this.query = new String(queryTmp, StandardCharsets.UTF_8);
			}
			this.limit = input.readInt();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ChatMembersFilterContacts.CONSTRUCTOR: this.filter = new ChatMembersFilterContacts(input); break;
					case ChatMembersFilterAdministrators.CONSTRUCTOR: this.filter = new ChatMembersFilterAdministrators(input); break;
					case ChatMembersFilterMembers.CONSTRUCTOR: this.filter = new ChatMembersFilterMembers(input); break;
					case ChatMembersFilterMention.CONSTRUCTOR: this.filter = new ChatMembersFilterMention(input); break;
					case ChatMembersFilterRestricted.CONSTRUCTOR: this.filter = new ChatMembersFilterRestricted(input); break;
					case ChatMembersFilterBanned.CONSTRUCTOR: this.filter = new ChatMembersFilterBanned(input); break;
					case ChatMembersFilterBots.CONSTRUCTOR: this.filter = new ChatMembersFilterBots(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SearchChatMembers.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SearchChatMembers.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.query == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] queryTmp = this.query.getBytes(StandardCharsets.UTF_8);
				output.writeInt(queryTmp.length);
				output.write(queryTmp);
			}
			output.writeInt(this.limit);
			if (this.filter == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.filter.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SearchChatMembers searchChatMembers = (SearchChatMembers) o;
			if (this.chatId != searchChatMembers.chatId) {
				return false;
			}
			if (this.query != searchChatMembers.query) {
				return false;
			}
			if (this.limit != searchChatMembers.limit) {
				return false;
			}
			if (!Objects.equals(this.filter, searchChatMembers.filter)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.query == null ? 0 : this.query.hashCode());
			result = result * 31 + (this.filter == null ? 0 : this.filter.hashCode());
			return result;
		}
	}

	/**
	 * Searches for messages with given words in the chat. Returns the
	 * results in reverse chronological order, i.e. in order of decreasing
	 * messageId. Cannot be used in secret chats with a non-empty query
	 * (searchSecretMessages must be used instead), or without an enabled
	 * message database. For optimal performance, the number of returned
	 * messages is chosen by TDLib and can be smaller than the specified
	 * limit. A combination of query, senderId, filter and messageThreadId
	 * search criteria is expected to be supported, only if it is required
	 * for Telegram official application implementation.
	 * <p> Returns {@link FoundChatMessages FoundChatMessages} </p>
	**/
	public static final class SearchChatMessages extends Function<FoundChatMessages> {


		/**
		 * Identifier of the chat in which to search messages.
		**/
		public long chatId;

		/**
		 * Query to search for.
		**/
		public String query;

		/**
		 * Identifier of the sender of messages to search for; pass null to search for messages from any sender. Not supported in secret chats.
		**/
		public MessageSender senderId;

		/**
		 * Identifier of the message starting from which history must be fetched; use 0 to get results from the last message.
		**/
		public long fromMessageId;

		/**
		 * Specify 0 to get results from exactly the fromMessageId or a negative offset to get the specified message and some newer messages.
		**/
		public int offset;

		/**
		 * The maximum number of messages to be returned; must be positive and can&#039;t be greater than 100. If the offset is negative, the limit must be greater than -offset. For optimal performance, the number of returned messages is chosen by TDLib and can be smaller than the specified limit.
		**/
		public int limit;

		/**
		 * Additional filter for messages to search; pass null to search for all messages.
		**/
		public SearchMessagesFilter filter;

		/**
		 * If not 0, only messages in the specified thread will be returned; supergroups only.
		**/
		public long messageThreadId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1879195132;

		/**
		 * Searches for messages with given words in the chat. Returns the results in reverse chronological order, i.e. in order of decreasing messageId. Cannot be used in secret chats with a non-empty query (searchSecretMessages must be used instead), or without an enabled message database. For optimal performance, the number of returned messages is chosen by TDLib and can be smaller than the specified limit. A combination of query, senderId, filter and messageThreadId search criteria is expected to be supported, only if it is required for Telegram official application implementation.
		 *
		 * <p> Returns {@link FoundChatMessages FoundChatMessages} </p>
		**/
		public SearchChatMessages() {}

		/**
		 * Searches for messages with given words in the chat. Returns the results in reverse chronological order, i.e. in order of decreasing messageId. Cannot be used in secret chats with a non-empty query (searchSecretMessages must be used instead), or without an enabled message database. For optimal performance, the number of returned messages is chosen by TDLib and can be smaller than the specified limit. A combination of query, senderId, filter and messageThreadId search criteria is expected to be supported, only if it is required for Telegram official application implementation.
		 *
		 * <p> Returns {@link FoundChatMessages FoundChatMessages} </p>
		 *
		 * @param chatId Identifier of the chat in which to search messages.
		 * @param query Query to search for.
		 * @param senderId Identifier of the sender of messages to search for; pass null to search for messages from any sender. Not supported in secret chats.
		 * @param fromMessageId Identifier of the message starting from which history must be fetched; use 0 to get results from the last message.
		 * @param offset Specify 0 to get results from exactly the fromMessageId or a negative offset to get the specified message and some newer messages.
		 * @param limit The maximum number of messages to be returned; must be positive and can&#039;t be greater than 100. If the offset is negative, the limit must be greater than -offset. For optimal performance, the number of returned messages is chosen by TDLib and can be smaller than the specified limit.
		 * @param filter Additional filter for messages to search; pass null to search for all messages.
		 * @param messageThreadId If not 0, only messages in the specified thread will be returned; supergroups only.
		 *
		 * <p> Returns {@link FoundChatMessages FoundChatMessages} </p>
		**/
		public SearchChatMessages(long chatId,
				String query,
				MessageSender senderId,
				long fromMessageId,
				int offset,
				int limit,
				SearchMessagesFilter filter,
				long messageThreadId) {
			this.chatId = chatId;
			this.query = query;
			this.senderId = senderId;
			this.fromMessageId = fromMessageId;
			this.offset = offset;
			this.limit = limit;
			this.filter = filter;
			this.messageThreadId = messageThreadId;
		}

		/**
		 * Searches for messages with given words in the chat. Returns the results in reverse chronological order, i.e. in order of decreasing messageId. Cannot be used in secret chats with a non-empty query (searchSecretMessages must be used instead), or without an enabled message database. For optimal performance, the number of returned messages is chosen by TDLib and can be smaller than the specified limit. A combination of query, senderId, filter and messageThreadId search criteria is expected to be supported, only if it is required for Telegram official application implementation.
		 *
		 * <p> Returns {@link FoundChatMessages FoundChatMessages} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SearchChatMessages(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				byte[] queryTmp = new byte[input.readInt()];
				input.readFully(queryTmp);
				this.query = new String(queryTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case MessageSenderUser.CONSTRUCTOR: this.senderId = new MessageSenderUser(input); break;
					case MessageSenderChat.CONSTRUCTOR: this.senderId = new MessageSenderChat(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.fromMessageId = input.readLong();
			this.offset = input.readInt();
			this.limit = input.readInt();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case SearchMessagesFilterEmpty.CONSTRUCTOR: this.filter = new SearchMessagesFilterEmpty(input); break;
					case SearchMessagesFilterAnimation.CONSTRUCTOR: this.filter = new SearchMessagesFilterAnimation(input); break;
					case SearchMessagesFilterAudio.CONSTRUCTOR: this.filter = new SearchMessagesFilterAudio(input); break;
					case SearchMessagesFilterDocument.CONSTRUCTOR: this.filter = new SearchMessagesFilterDocument(input); break;
					case SearchMessagesFilterPhoto.CONSTRUCTOR: this.filter = new SearchMessagesFilterPhoto(input); break;
					case SearchMessagesFilterVideo.CONSTRUCTOR: this.filter = new SearchMessagesFilterVideo(input); break;
					case SearchMessagesFilterVoiceNote.CONSTRUCTOR: this.filter = new SearchMessagesFilterVoiceNote(input); break;
					case SearchMessagesFilterPhotoAndVideo.CONSTRUCTOR: this.filter = new SearchMessagesFilterPhotoAndVideo(input); break;
					case SearchMessagesFilterUrl.CONSTRUCTOR: this.filter = new SearchMessagesFilterUrl(input); break;
					case SearchMessagesFilterChatPhoto.CONSTRUCTOR: this.filter = new SearchMessagesFilterChatPhoto(input); break;
					case SearchMessagesFilterVideoNote.CONSTRUCTOR: this.filter = new SearchMessagesFilterVideoNote(input); break;
					case SearchMessagesFilterVoiceAndVideoNote.CONSTRUCTOR: this.filter = new SearchMessagesFilterVoiceAndVideoNote(input); break;
					case SearchMessagesFilterMention.CONSTRUCTOR: this.filter = new SearchMessagesFilterMention(input); break;
					case SearchMessagesFilterUnreadMention.CONSTRUCTOR: this.filter = new SearchMessagesFilterUnreadMention(input); break;
					case SearchMessagesFilterUnreadReaction.CONSTRUCTOR: this.filter = new SearchMessagesFilterUnreadReaction(input); break;
					case SearchMessagesFilterFailedToSend.CONSTRUCTOR: this.filter = new SearchMessagesFilterFailedToSend(input); break;
					case SearchMessagesFilterPinned.CONSTRUCTOR: this.filter = new SearchMessagesFilterPinned(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.messageThreadId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SearchChatMessages.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SearchChatMessages.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.query == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] queryTmp = this.query.getBytes(StandardCharsets.UTF_8);
				output.writeInt(queryTmp.length);
				output.write(queryTmp);
			}
			if (this.senderId == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.senderId.serialize(output);
			}
			output.writeLong(this.fromMessageId);
			output.writeInt(this.offset);
			output.writeInt(this.limit);
			if (this.filter == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.filter.serialize(output);
			}
			output.writeLong(this.messageThreadId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SearchChatMessages searchChatMessages = (SearchChatMessages) o;
			if (this.chatId != searchChatMessages.chatId) {
				return false;
			}
			if (this.query != searchChatMessages.query) {
				return false;
			}
			if (!Objects.equals(this.senderId, searchChatMessages.senderId)) {
				return false;
			}
			if (this.fromMessageId != searchChatMessages.fromMessageId) {
				return false;
			}
			if (this.offset != searchChatMessages.offset) {
				return false;
			}
			if (this.limit != searchChatMessages.limit) {
				return false;
			}
			if (!Objects.equals(this.filter, searchChatMessages.filter)) {
				return false;
			}
			if (this.messageThreadId != searchChatMessages.messageThreadId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.query == null ? 0 : this.query.hashCode());
			result = result * 31 + (this.senderId == null ? 0 : this.senderId.hashCode());
			result = result * 31 + (this.filter == null ? 0 : this.filter.hashCode());
			return result;
		}
	}

	/**
	 * Returns information about the recent locations of chat members that
	 * were sent to the chat. Returns up to 1 location message per user.
	 * <p> Returns {@link Messages Messages} </p>
	**/
	public static final class SearchChatRecentLocationMessages extends Function<Messages> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * The maximum number of messages to be returned.
		**/
		public int limit;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 950238950;

		/**
		 * Returns information about the recent locations of chat members that were sent to the chat. Returns up to 1 location message per user.
		 *
		 * <p> Returns {@link Messages Messages} </p>
		**/
		public SearchChatRecentLocationMessages() {}

		/**
		 * Returns information about the recent locations of chat members that were sent to the chat. Returns up to 1 location message per user.
		 *
		 * <p> Returns {@link Messages Messages} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param limit The maximum number of messages to be returned.
		 *
		 * <p> Returns {@link Messages Messages} </p>
		**/
		public SearchChatRecentLocationMessages(long chatId, int limit) {
			this.chatId = chatId;
			this.limit = limit;
		}

		/**
		 * Returns information about the recent locations of chat members that were sent to the chat. Returns up to 1 location message per user.
		 *
		 * <p> Returns {@link Messages Messages} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SearchChatRecentLocationMessages(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.limit = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SearchChatRecentLocationMessages.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SearchChatRecentLocationMessages.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeInt(this.limit);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SearchChatRecentLocationMessages searchChatRecentLocationMessages = (SearchChatRecentLocationMessages) o;
			if (this.chatId != searchChatRecentLocationMessages.chatId) {
				return false;
			}
			if (this.limit != searchChatRecentLocationMessages.limit) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Searches for the specified query in the title and username of already
	 * known chats, this is an offline request. Returns chats in the order
	 * seen in the main chat list.
	 * <p> Returns {@link Chats Chats} </p>
	**/
	public static final class SearchChats extends Function<Chats> {


		/**
		 * Query to search for. If the query is empty, returns up to 50 recently found chats.
		**/
		public String query;

		/**
		 * The maximum number of chats to be returned.
		**/
		public int limit;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1879787060;

		/**
		 * Searches for the specified query in the title and username of already known chats, this is an offline request. Returns chats in the order seen in the main chat list.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		**/
		public SearchChats() {}

		/**
		 * Searches for the specified query in the title and username of already known chats, this is an offline request. Returns chats in the order seen in the main chat list.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		 *
		 * @param query Query to search for. If the query is empty, returns up to 50 recently found chats.
		 * @param limit The maximum number of chats to be returned.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		**/
		public SearchChats(String query, int limit) {
			this.query = query;
			this.limit = limit;
		}

		/**
		 * Searches for the specified query in the title and username of already known chats, this is an offline request. Returns chats in the order seen in the main chat list.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SearchChats(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] queryTmp = new byte[input.readInt()];
				input.readFully(queryTmp);
				this.query = new String(queryTmp, StandardCharsets.UTF_8);
			}
			this.limit = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SearchChats.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SearchChats.CONSTRUCTOR);
			if (this.query == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] queryTmp = this.query.getBytes(StandardCharsets.UTF_8);
				output.writeInt(queryTmp.length);
				output.write(queryTmp);
			}
			output.writeInt(this.limit);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SearchChats searchChats = (SearchChats) o;
			if (this.query != searchChats.query) {
				return false;
			}
			if (this.limit != searchChats.limit) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.limit);
			result = result * 31 + (this.query == null ? 0 : this.query.hashCode());
			return result;
		}
	}

	/**
	 * Returns a list of users and location-based supergroups nearby. The
	 * list of users nearby will be updated for 60 seconds after the request
	 * by the updates updateUsersNearby. The request must be sent again
	 * every 25 seconds with adjusted location to not miss new chats.
	 * <p> Returns {@link ChatsNearby ChatsNearby} </p>
	**/
	public static final class SearchChatsNearby extends Function<ChatsNearby> {


		/**
		 * Current user location.
		**/
		public Location location;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -196753377;

		/**
		 * Returns a list of users and location-based supergroups nearby. The list of users nearby will be updated for 60 seconds after the request by the updates updateUsersNearby. The request must be sent again every 25 seconds with adjusted location to not miss new chats.
		 *
		 * <p> Returns {@link ChatsNearby ChatsNearby} </p>
		**/
		public SearchChatsNearby() {}

		/**
		 * Returns a list of users and location-based supergroups nearby. The list of users nearby will be updated for 60 seconds after the request by the updates updateUsersNearby. The request must be sent again every 25 seconds with adjusted location to not miss new chats.
		 *
		 * <p> Returns {@link ChatsNearby ChatsNearby} </p>
		 *
		 * @param location Current user location.
		 *
		 * <p> Returns {@link ChatsNearby ChatsNearby} </p>
		**/
		public SearchChatsNearby(Location location) {
			this.location = location;
		}

		/**
		 * Returns a list of users and location-based supergroups nearby. The list of users nearby will be updated for 60 seconds after the request by the updates updateUsersNearby. The request must be sent again every 25 seconds with adjusted location to not miss new chats.
		 *
		 * <p> Returns {@link ChatsNearby ChatsNearby} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SearchChatsNearby(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Location.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.location = new Location(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SearchChatsNearby.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SearchChatsNearby.CONSTRUCTOR);
			if (this.location == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.location.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SearchChatsNearby searchChatsNearby = (SearchChatsNearby) o;
			if (!Objects.equals(this.location, searchChatsNearby.location)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.location == null ? 0 : this.location.hashCode();
		}
	}

	/**
	 * Searches for the specified query in the title and username of already
	 * known chats via request to the server. Returns chats in the order
	 * seen in the main chat list.
	 * <p> Returns {@link Chats Chats} </p>
	**/
	public static final class SearchChatsOnServer extends Function<Chats> {


		/**
		 * Query to search for.
		**/
		public String query;

		/**
		 * The maximum number of chats to be returned.
		**/
		public int limit;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1158402188;

		/**
		 * Searches for the specified query in the title and username of already known chats via request to the server. Returns chats in the order seen in the main chat list.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		**/
		public SearchChatsOnServer() {}

		/**
		 * Searches for the specified query in the title and username of already known chats via request to the server. Returns chats in the order seen in the main chat list.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		 *
		 * @param query Query to search for.
		 * @param limit The maximum number of chats to be returned.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		**/
		public SearchChatsOnServer(String query, int limit) {
			this.query = query;
			this.limit = limit;
		}

		/**
		 * Searches for the specified query in the title and username of already known chats via request to the server. Returns chats in the order seen in the main chat list.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SearchChatsOnServer(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] queryTmp = new byte[input.readInt()];
				input.readFully(queryTmp);
				this.query = new String(queryTmp, StandardCharsets.UTF_8);
			}
			this.limit = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SearchChatsOnServer.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SearchChatsOnServer.CONSTRUCTOR);
			if (this.query == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] queryTmp = this.query.getBytes(StandardCharsets.UTF_8);
				output.writeInt(queryTmp.length);
				output.write(queryTmp);
			}
			output.writeInt(this.limit);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SearchChatsOnServer searchChatsOnServer = (SearchChatsOnServer) o;
			if (this.query != searchChatsOnServer.query) {
				return false;
			}
			if (this.limit != searchChatsOnServer.limit) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.limit);
			result = result * 31 + (this.query == null ? 0 : this.query.hashCode());
			return result;
		}
	}

	/**
	 * Searches for the specified query in the first names, last names and
	 * usernames of the known user contacts.
	 * <p> Returns {@link Users Users} </p>
	**/
	public static final class SearchContacts extends Function<Users> {


		/**
		 * Query to search for; may be empty to return all contacts.
		**/
		public String query;

		/**
		 * The maximum number of users to be returned.
		**/
		public int limit;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1794690715;

		/**
		 * Searches for the specified query in the first names, last names and usernames of the known user contacts.
		 *
		 * <p> Returns {@link Users Users} </p>
		**/
		public SearchContacts() {}

		/**
		 * Searches for the specified query in the first names, last names and usernames of the known user contacts.
		 *
		 * <p> Returns {@link Users Users} </p>
		 *
		 * @param query Query to search for; may be empty to return all contacts.
		 * @param limit The maximum number of users to be returned.
		 *
		 * <p> Returns {@link Users Users} </p>
		**/
		public SearchContacts(String query, int limit) {
			this.query = query;
			this.limit = limit;
		}

		/**
		 * Searches for the specified query in the first names, last names and usernames of the known user contacts.
		 *
		 * <p> Returns {@link Users Users} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SearchContacts(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] queryTmp = new byte[input.readInt()];
				input.readFully(queryTmp);
				this.query = new String(queryTmp, StandardCharsets.UTF_8);
			}
			this.limit = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SearchContacts.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SearchContacts.CONSTRUCTOR);
			if (this.query == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] queryTmp = this.query.getBytes(StandardCharsets.UTF_8);
				output.writeInt(queryTmp.length);
				output.write(queryTmp);
			}
			output.writeInt(this.limit);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SearchContacts searchContacts = (SearchContacts) o;
			if (this.query != searchContacts.query) {
				return false;
			}
			if (this.limit != searchContacts.limit) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.limit);
			result = result * 31 + (this.query == null ? 0 : this.query.hashCode());
			return result;
		}
	}

	/**
	 * Searches for emojis by keywords. Supported only if the file database
	 * is enabled.
	 * <p> Returns {@link Emojis Emojis} </p>
	**/
	public static final class SearchEmojis extends Function<Emojis> {


		/**
		 * Text to search for.
		**/
		public String text;

		/**
		 * Pass true if only emojis, which exactly match the text, needs to be returned.
		**/
		public boolean exactMatch;

		/**
		 * List of possible IETF language tags of the user&#039;s input language; may be empty if unknown.
		**/
		public String[] inputLanguageCodes;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 398837927;

		/**
		 * Searches for emojis by keywords. Supported only if the file database is enabled.
		 *
		 * <p> Returns {@link Emojis Emojis} </p>
		**/
		public SearchEmojis() {}

		/**
		 * Searches for emojis by keywords. Supported only if the file database is enabled.
		 *
		 * <p> Returns {@link Emojis Emojis} </p>
		 *
		 * @param text Text to search for.
		 * @param exactMatch Pass true if only emojis, which exactly match the text, needs to be returned.
		 * @param inputLanguageCodes List of possible IETF language tags of the user&#039;s input language; may be empty if unknown.
		 *
		 * <p> Returns {@link Emojis Emojis} </p>
		**/
		public SearchEmojis(String text, boolean exactMatch, String[] inputLanguageCodes) {
			this.text = text;
			this.exactMatch = exactMatch;
			this.inputLanguageCodes = inputLanguageCodes;
		}

		/**
		 * Searches for emojis by keywords. Supported only if the file database is enabled.
		 *
		 * <p> Returns {@link Emojis Emojis} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SearchEmojis(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] textTmp = new byte[input.readInt()];
				input.readFully(textTmp);
				this.text = new String(textTmp, StandardCharsets.UTF_8);
			}
			this.exactMatch = input.readBoolean();
			if (input.readBoolean()) {
				this.inputLanguageCodes = new String[input.readInt()];
				for (int i = 0; i < this.inputLanguageCodes.length; i++) {
					byte[] inputLanguageCodesTmp = new byte[input.readInt()];
					input.readFully(inputLanguageCodesTmp);
					this.inputLanguageCodes[i] = new String(inputLanguageCodesTmp, StandardCharsets.UTF_8);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SearchEmojis.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SearchEmojis.CONSTRUCTOR);
			if (this.text == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] textTmp = this.text.getBytes(StandardCharsets.UTF_8);
				output.writeInt(textTmp.length);
				output.write(textTmp);
			}
			output.writeBoolean(this.exactMatch);
			if (this.inputLanguageCodes == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.inputLanguageCodes.length);
				for (int i = 0; i < this.inputLanguageCodes.length; i++) {
					byte[] inputLanguageCodesTmp = this.inputLanguageCodes[i].getBytes(StandardCharsets.UTF_8);
					output.writeInt(inputLanguageCodesTmp.length);
					output.write(inputLanguageCodesTmp);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SearchEmojis searchEmojis = (SearchEmojis) o;
			if (this.text != searchEmojis.text) {
				return false;
			}
			if (this.exactMatch != searchEmojis.exactMatch) {
				return false;
			}
			if (!Arrays.equals(this.inputLanguageCodes, searchEmojis.inputLanguageCodes)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.exactMatch);
			result = result * 31 + (this.text == null ? 0 : this.text.hashCode());
			result = result * 31 + (Arrays.hashCode(this.inputLanguageCodes));
			return result;
		}
	}

	/**
	 * Searches for files in the file download list or recently downloaded
	 * files from the list.
	 * <p> Returns {@link FoundFileDownloads FoundFileDownloads} </p>
	**/
	public static final class SearchFileDownloads extends Function<FoundFileDownloads> {


		/**
		 * Query to search for; may be empty to return all downloaded files.
		**/
		public String query;

		/**
		 * Pass true to search only for active downloads, including paused.
		**/
		public boolean onlyActive;

		/**
		 * Pass true to search only for completed downloads.
		**/
		public boolean onlyCompleted;

		/**
		 * Offset of the first entry to return as received from the previous request; use empty string to get the first chunk of results.
		**/
		public String offset;

		/**
		 * The maximum number of files to be returned.
		**/
		public int limit;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 706611286;

		/**
		 * Searches for files in the file download list or recently downloaded files from the list.
		 *
		 * <p> Returns {@link FoundFileDownloads FoundFileDownloads} </p>
		**/
		public SearchFileDownloads() {}

		/**
		 * Searches for files in the file download list or recently downloaded files from the list.
		 *
		 * <p> Returns {@link FoundFileDownloads FoundFileDownloads} </p>
		 *
		 * @param query Query to search for; may be empty to return all downloaded files.
		 * @param onlyActive Pass true to search only for active downloads, including paused.
		 * @param onlyCompleted Pass true to search only for completed downloads.
		 * @param offset Offset of the first entry to return as received from the previous request; use empty string to get the first chunk of results.
		 * @param limit The maximum number of files to be returned.
		 *
		 * <p> Returns {@link FoundFileDownloads FoundFileDownloads} </p>
		**/
		public SearchFileDownloads(String query,
				boolean onlyActive,
				boolean onlyCompleted,
				String offset,
				int limit) {
			this.query = query;
			this.onlyActive = onlyActive;
			this.onlyCompleted = onlyCompleted;
			this.offset = offset;
			this.limit = limit;
		}

		/**
		 * Searches for files in the file download list or recently downloaded files from the list.
		 *
		 * <p> Returns {@link FoundFileDownloads FoundFileDownloads} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SearchFileDownloads(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] queryTmp = new byte[input.readInt()];
				input.readFully(queryTmp);
				this.query = new String(queryTmp, StandardCharsets.UTF_8);
			}
			this.onlyActive = input.readBoolean();
			this.onlyCompleted = input.readBoolean();
			if (input.readBoolean()) {
				byte[] offsetTmp = new byte[input.readInt()];
				input.readFully(offsetTmp);
				this.offset = new String(offsetTmp, StandardCharsets.UTF_8);
			}
			this.limit = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SearchFileDownloads.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SearchFileDownloads.CONSTRUCTOR);
			if (this.query == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] queryTmp = this.query.getBytes(StandardCharsets.UTF_8);
				output.writeInt(queryTmp.length);
				output.write(queryTmp);
			}
			output.writeBoolean(this.onlyActive);
			output.writeBoolean(this.onlyCompleted);
			if (this.offset == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] offsetTmp = this.offset.getBytes(StandardCharsets.UTF_8);
				output.writeInt(offsetTmp.length);
				output.write(offsetTmp);
			}
			output.writeInt(this.limit);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SearchFileDownloads searchFileDownloads = (SearchFileDownloads) o;
			if (this.query != searchFileDownloads.query) {
				return false;
			}
			if (this.onlyActive != searchFileDownloads.onlyActive) {
				return false;
			}
			if (this.onlyCompleted != searchFileDownloads.onlyCompleted) {
				return false;
			}
			if (this.offset != searchFileDownloads.offset) {
				return false;
			}
			if (this.limit != searchFileDownloads.limit) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.onlyActive);
			result = result * 31 + (this.query == null ? 0 : this.query.hashCode());
			result = result * 31 + (this.offset == null ? 0 : this.offset.hashCode());
			return result;
		}
	}

	/**
	 * Searches for recently used hashtags by their prefix.
	 * <p> Returns {@link Hashtags Hashtags} </p>
	**/
	public static final class SearchHashtags extends Function<Hashtags> {


		/**
		 * Hashtag prefix to search for.
		**/
		public String prefix;

		/**
		 * The maximum number of hashtags to be returned.
		**/
		public int limit;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1043637617;

		/**
		 * Searches for recently used hashtags by their prefix.
		 *
		 * <p> Returns {@link Hashtags Hashtags} </p>
		**/
		public SearchHashtags() {}

		/**
		 * Searches for recently used hashtags by their prefix.
		 *
		 * <p> Returns {@link Hashtags Hashtags} </p>
		 *
		 * @param prefix Hashtag prefix to search for.
		 * @param limit The maximum number of hashtags to be returned.
		 *
		 * <p> Returns {@link Hashtags Hashtags} </p>
		**/
		public SearchHashtags(String prefix, int limit) {
			this.prefix = prefix;
			this.limit = limit;
		}

		/**
		 * Searches for recently used hashtags by their prefix.
		 *
		 * <p> Returns {@link Hashtags Hashtags} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SearchHashtags(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] prefixTmp = new byte[input.readInt()];
				input.readFully(prefixTmp);
				this.prefix = new String(prefixTmp, StandardCharsets.UTF_8);
			}
			this.limit = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SearchHashtags.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SearchHashtags.CONSTRUCTOR);
			if (this.prefix == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] prefixTmp = this.prefix.getBytes(StandardCharsets.UTF_8);
				output.writeInt(prefixTmp.length);
				output.write(prefixTmp);
			}
			output.writeInt(this.limit);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SearchHashtags searchHashtags = (SearchHashtags) o;
			if (this.prefix != searchHashtags.prefix) {
				return false;
			}
			if (this.limit != searchHashtags.limit) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.limit);
			result = result * 31 + (this.prefix == null ? 0 : this.prefix.hashCode());
			return result;
		}
	}

	/**
	 * Searches for installed sticker sets by looking for specified query in
	 * their title and name.
	 * <p> Returns {@link StickerSets StickerSets} </p>
	**/
	public static final class SearchInstalledStickerSets extends Function<StickerSets> {


		/**
		 * Type of the sticker sets to search for.
		**/
		public StickerType stickerType;

		/**
		 * Query to search for.
		**/
		public String query;

		/**
		 * The maximum number of sticker sets to return.
		**/
		public int limit;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2120122276;

		/**
		 * Searches for installed sticker sets by looking for specified query in their title and name.
		 *
		 * <p> Returns {@link StickerSets StickerSets} </p>
		**/
		public SearchInstalledStickerSets() {}

		/**
		 * Searches for installed sticker sets by looking for specified query in their title and name.
		 *
		 * <p> Returns {@link StickerSets StickerSets} </p>
		 *
		 * @param stickerType Type of the sticker sets to search for.
		 * @param query Query to search for.
		 * @param limit The maximum number of sticker sets to return.
		 *
		 * <p> Returns {@link StickerSets StickerSets} </p>
		**/
		public SearchInstalledStickerSets(StickerType stickerType, String query, int limit) {
			this.stickerType = stickerType;
			this.query = query;
			this.limit = limit;
		}

		/**
		 * Searches for installed sticker sets by looking for specified query in their title and name.
		 *
		 * <p> Returns {@link StickerSets StickerSets} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SearchInstalledStickerSets(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case StickerTypeRegular.CONSTRUCTOR: this.stickerType = new StickerTypeRegular(input); break;
					case StickerTypeMask.CONSTRUCTOR: this.stickerType = new StickerTypeMask(input); break;
					case StickerTypeCustomEmoji.CONSTRUCTOR: this.stickerType = new StickerTypeCustomEmoji(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				byte[] queryTmp = new byte[input.readInt()];
				input.readFully(queryTmp);
				this.query = new String(queryTmp, StandardCharsets.UTF_8);
			}
			this.limit = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SearchInstalledStickerSets.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SearchInstalledStickerSets.CONSTRUCTOR);
			if (this.stickerType == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.stickerType.serialize(output);
			}
			if (this.query == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] queryTmp = this.query.getBytes(StandardCharsets.UTF_8);
				output.writeInt(queryTmp.length);
				output.write(queryTmp);
			}
			output.writeInt(this.limit);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SearchInstalledStickerSets searchInstalledStickerSets = (SearchInstalledStickerSets) o;
			if (!Objects.equals(this.stickerType, searchInstalledStickerSets.stickerType)) {
				return false;
			}
			if (this.query != searchInstalledStickerSets.query) {
				return false;
			}
			if (this.limit != searchInstalledStickerSets.limit) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.limit);
			result = result * 31 + (this.stickerType == null ? 0 : this.stickerType.hashCode());
			result = result * 31 + (this.query == null ? 0 : this.query.hashCode());
			return result;
		}
	}

	/**
	 * Searches for messages in all chats except secret chats. Returns the
	 * results in reverse chronological order (i.e., in order of decreasing
	 * (date, chatId, messageId)). For optimal performance, the number of
	 * returned messages is chosen by TDLib and can be smaller than the
	 * specified limit.
	 * <p> Returns {@link FoundMessages FoundMessages} </p>
	**/
	public static final class SearchMessages extends Function<FoundMessages> {


		/**
		 * Chat list in which to search messages; pass null to search in all chats regardless of their chat list. Only Main and Archive chat lists are supported.
		**/
		public ChatList chatList;

		/**
		 * Query to search for.
		**/
		public String query;

		/**
		 * Offset of the first entry to return as received from the previous request; use empty string to get the first chunk of results.
		**/
		public String offset;

		/**
		 * The maximum number of messages to be returned; up to 100. For optimal performance, the number of returned messages is chosen by TDLib and can be smaller than the specified limit.
		**/
		public int limit;

		/**
		 * Additional filter for messages to search; pass null to search for all messages. Filters searchMessagesFilterMention, searchMessagesFilterUnreadMention, searchMessagesFilterUnreadReaction, searchMessagesFilterFailedToSend, and searchMessagesFilterPinned are unsupported in this function.
		**/
		public SearchMessagesFilter filter;

		/**
		 * If not 0, the minimum date of the messages to return.
		**/
		public int minDate;

		/**
		 * If not 0, the maximum date of the messages to return.
		**/
		public int maxDate;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 714016935;

		/**
		 * Searches for messages in all chats except secret chats. Returns the results in reverse chronological order (i.e., in order of decreasing (date, chatId, messageId)). For optimal performance, the number of returned messages is chosen by TDLib and can be smaller than the specified limit.
		 *
		 * <p> Returns {@link FoundMessages FoundMessages} </p>
		**/
		public SearchMessages() {}

		/**
		 * Searches for messages in all chats except secret chats. Returns the results in reverse chronological order (i.e., in order of decreasing (date, chatId, messageId)). For optimal performance, the number of returned messages is chosen by TDLib and can be smaller than the specified limit.
		 *
		 * <p> Returns {@link FoundMessages FoundMessages} </p>
		 *
		 * @param chatList Chat list in which to search messages; pass null to search in all chats regardless of their chat list. Only Main and Archive chat lists are supported.
		 * @param query Query to search for.
		 * @param offset Offset of the first entry to return as received from the previous request; use empty string to get the first chunk of results.
		 * @param limit The maximum number of messages to be returned; up to 100. For optimal performance, the number of returned messages is chosen by TDLib and can be smaller than the specified limit.
		 * @param filter Additional filter for messages to search; pass null to search for all messages. Filters searchMessagesFilterMention, searchMessagesFilterUnreadMention, searchMessagesFilterUnreadReaction, searchMessagesFilterFailedToSend, and searchMessagesFilterPinned are unsupported in this function.
		 * @param minDate If not 0, the minimum date of the messages to return.
		 * @param maxDate If not 0, the maximum date of the messages to return.
		 *
		 * <p> Returns {@link FoundMessages FoundMessages} </p>
		**/
		public SearchMessages(ChatList chatList,
				String query,
				String offset,
				int limit,
				SearchMessagesFilter filter,
				int minDate,
				int maxDate) {
			this.chatList = chatList;
			this.query = query;
			this.offset = offset;
			this.limit = limit;
			this.filter = filter;
			this.minDate = minDate;
			this.maxDate = maxDate;
		}

		/**
		 * Searches for messages in all chats except secret chats. Returns the results in reverse chronological order (i.e., in order of decreasing (date, chatId, messageId)). For optimal performance, the number of returned messages is chosen by TDLib and can be smaller than the specified limit.
		 *
		 * <p> Returns {@link FoundMessages FoundMessages} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SearchMessages(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ChatListMain.CONSTRUCTOR: this.chatList = new ChatListMain(input); break;
					case ChatListArchive.CONSTRUCTOR: this.chatList = new ChatListArchive(input); break;
					case ChatListFolder.CONSTRUCTOR: this.chatList = new ChatListFolder(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				byte[] queryTmp = new byte[input.readInt()];
				input.readFully(queryTmp);
				this.query = new String(queryTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] offsetTmp = new byte[input.readInt()];
				input.readFully(offsetTmp);
				this.offset = new String(offsetTmp, StandardCharsets.UTF_8);
			}
			this.limit = input.readInt();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case SearchMessagesFilterEmpty.CONSTRUCTOR: this.filter = new SearchMessagesFilterEmpty(input); break;
					case SearchMessagesFilterAnimation.CONSTRUCTOR: this.filter = new SearchMessagesFilterAnimation(input); break;
					case SearchMessagesFilterAudio.CONSTRUCTOR: this.filter = new SearchMessagesFilterAudio(input); break;
					case SearchMessagesFilterDocument.CONSTRUCTOR: this.filter = new SearchMessagesFilterDocument(input); break;
					case SearchMessagesFilterPhoto.CONSTRUCTOR: this.filter = new SearchMessagesFilterPhoto(input); break;
					case SearchMessagesFilterVideo.CONSTRUCTOR: this.filter = new SearchMessagesFilterVideo(input); break;
					case SearchMessagesFilterVoiceNote.CONSTRUCTOR: this.filter = new SearchMessagesFilterVoiceNote(input); break;
					case SearchMessagesFilterPhotoAndVideo.CONSTRUCTOR: this.filter = new SearchMessagesFilterPhotoAndVideo(input); break;
					case SearchMessagesFilterUrl.CONSTRUCTOR: this.filter = new SearchMessagesFilterUrl(input); break;
					case SearchMessagesFilterChatPhoto.CONSTRUCTOR: this.filter = new SearchMessagesFilterChatPhoto(input); break;
					case SearchMessagesFilterVideoNote.CONSTRUCTOR: this.filter = new SearchMessagesFilterVideoNote(input); break;
					case SearchMessagesFilterVoiceAndVideoNote.CONSTRUCTOR: this.filter = new SearchMessagesFilterVoiceAndVideoNote(input); break;
					case SearchMessagesFilterMention.CONSTRUCTOR: this.filter = new SearchMessagesFilterMention(input); break;
					case SearchMessagesFilterUnreadMention.CONSTRUCTOR: this.filter = new SearchMessagesFilterUnreadMention(input); break;
					case SearchMessagesFilterUnreadReaction.CONSTRUCTOR: this.filter = new SearchMessagesFilterUnreadReaction(input); break;
					case SearchMessagesFilterFailedToSend.CONSTRUCTOR: this.filter = new SearchMessagesFilterFailedToSend(input); break;
					case SearchMessagesFilterPinned.CONSTRUCTOR: this.filter = new SearchMessagesFilterPinned(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.minDate = input.readInt();
			this.maxDate = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SearchMessages.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SearchMessages.CONSTRUCTOR);
			if (this.chatList == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.chatList.serialize(output);
			}
			if (this.query == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] queryTmp = this.query.getBytes(StandardCharsets.UTF_8);
				output.writeInt(queryTmp.length);
				output.write(queryTmp);
			}
			if (this.offset == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] offsetTmp = this.offset.getBytes(StandardCharsets.UTF_8);
				output.writeInt(offsetTmp.length);
				output.write(offsetTmp);
			}
			output.writeInt(this.limit);
			if (this.filter == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.filter.serialize(output);
			}
			output.writeInt(this.minDate);
			output.writeInt(this.maxDate);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SearchMessages searchMessages = (SearchMessages) o;
			if (!Objects.equals(this.chatList, searchMessages.chatList)) {
				return false;
			}
			if (this.query != searchMessages.query) {
				return false;
			}
			if (this.offset != searchMessages.offset) {
				return false;
			}
			if (this.limit != searchMessages.limit) {
				return false;
			}
			if (!Objects.equals(this.filter, searchMessages.filter)) {
				return false;
			}
			if (this.minDate != searchMessages.minDate) {
				return false;
			}
			if (this.maxDate != searchMessages.maxDate) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.limit);
			result = result * 31 + (this.chatList == null ? 0 : this.chatList.hashCode());
			result = result * 31 + (this.query == null ? 0 : this.query.hashCode());
			result = result * 31 + (this.offset == null ? 0 : this.offset.hashCode());
			result = result * 31 + (this.filter == null ? 0 : this.filter.hashCode());
			return result;
		}
	}

	/**
	 * Searches for outgoing messages with content of the type
	 * messageDocument in all chats except secret chats. Returns the results
	 * in reverse chronological order.
	 * <p> Returns {@link FoundMessages FoundMessages} </p>
	**/
	public static final class SearchOutgoingDocumentMessages extends Function<FoundMessages> {


		/**
		 * Query to search for in document file name and message caption.
		**/
		public String query;

		/**
		 * The maximum number of messages to be returned; up to 100.
		**/
		public int limit;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1071397762;

		/**
		 * Searches for outgoing messages with content of the type messageDocument in all chats except secret chats. Returns the results in reverse chronological order.
		 *
		 * <p> Returns {@link FoundMessages FoundMessages} </p>
		**/
		public SearchOutgoingDocumentMessages() {}

		/**
		 * Searches for outgoing messages with content of the type messageDocument in all chats except secret chats. Returns the results in reverse chronological order.
		 *
		 * <p> Returns {@link FoundMessages FoundMessages} </p>
		 *
		 * @param query Query to search for in document file name and message caption.
		 * @param limit The maximum number of messages to be returned; up to 100.
		 *
		 * <p> Returns {@link FoundMessages FoundMessages} </p>
		**/
		public SearchOutgoingDocumentMessages(String query, int limit) {
			this.query = query;
			this.limit = limit;
		}

		/**
		 * Searches for outgoing messages with content of the type messageDocument in all chats except secret chats. Returns the results in reverse chronological order.
		 *
		 * <p> Returns {@link FoundMessages FoundMessages} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SearchOutgoingDocumentMessages(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] queryTmp = new byte[input.readInt()];
				input.readFully(queryTmp);
				this.query = new String(queryTmp, StandardCharsets.UTF_8);
			}
			this.limit = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SearchOutgoingDocumentMessages.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SearchOutgoingDocumentMessages.CONSTRUCTOR);
			if (this.query == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] queryTmp = this.query.getBytes(StandardCharsets.UTF_8);
				output.writeInt(queryTmp.length);
				output.write(queryTmp);
			}
			output.writeInt(this.limit);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SearchOutgoingDocumentMessages searchOutgoingDocumentMessages = (SearchOutgoingDocumentMessages) o;
			if (this.query != searchOutgoingDocumentMessages.query) {
				return false;
			}
			if (this.limit != searchOutgoingDocumentMessages.limit) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.limit);
			result = result * 31 + (this.query == null ? 0 : this.query.hashCode());
			return result;
		}
	}

	/**
	 * Searches a public chat by its username. Currently, only private
	 * chats, supergroups and channels can be public. Returns the chat if
	 * found; otherwise, an error is returned.
	 * <p> Returns {@link Chat Chat} </p>
	**/
	public static final class SearchPublicChat extends Function<Chat> {


		/**
		 * Username to be resolved.
		**/
		public String username;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 857135533;

		/**
		 * Searches a public chat by its username. Currently, only private chats, supergroups and channels can be public. Returns the chat if found; otherwise, an error is returned.
		 *
		 * <p> Returns {@link Chat Chat} </p>
		**/
		public SearchPublicChat() {}

		/**
		 * Searches a public chat by its username. Currently, only private chats, supergroups and channels can be public. Returns the chat if found; otherwise, an error is returned.
		 *
		 * <p> Returns {@link Chat Chat} </p>
		 *
		 * @param username Username to be resolved.
		 *
		 * <p> Returns {@link Chat Chat} </p>
		**/
		public SearchPublicChat(String username) {
			this.username = username;
		}

		/**
		 * Searches a public chat by its username. Currently, only private chats, supergroups and channels can be public. Returns the chat if found; otherwise, an error is returned.
		 *
		 * <p> Returns {@link Chat Chat} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SearchPublicChat(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] usernameTmp = new byte[input.readInt()];
				input.readFully(usernameTmp);
				this.username = new String(usernameTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SearchPublicChat.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SearchPublicChat.CONSTRUCTOR);
			if (this.username == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] usernameTmp = this.username.getBytes(StandardCharsets.UTF_8);
				output.writeInt(usernameTmp.length);
				output.write(usernameTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SearchPublicChat searchPublicChat = (SearchPublicChat) o;
			if (this.username != searchPublicChat.username) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.username == null ? 0 : this.username.hashCode();
		}
	}

	/**
	 * Searches public chats by looking for specified query in their
	 * username and title. Currently, only private chats, supergroups and
	 * channels can be public. Returns a meaningful number of results.
	 * Excludes private chats with contacts and chats from the chat list
	 * from the results.
	 * <p> Returns {@link Chats Chats} </p>
	**/
	public static final class SearchPublicChats extends Function<Chats> {


		/**
		 * Query to search for.
		**/
		public String query;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 970385337;

		/**
		 * Searches public chats by looking for specified query in their username and title. Currently, only private chats, supergroups and channels can be public. Returns a meaningful number of results. Excludes private chats with contacts and chats from the chat list from the results.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		**/
		public SearchPublicChats() {}

		/**
		 * Searches public chats by looking for specified query in their username and title. Currently, only private chats, supergroups and channels can be public. Returns a meaningful number of results. Excludes private chats with contacts and chats from the chat list from the results.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		 *
		 * @param query Query to search for.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		**/
		public SearchPublicChats(String query) {
			this.query = query;
		}

		/**
		 * Searches public chats by looking for specified query in their username and title. Currently, only private chats, supergroups and channels can be public. Returns a meaningful number of results. Excludes private chats with contacts and chats from the chat list from the results.
		 *
		 * <p> Returns {@link Chats Chats} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SearchPublicChats(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] queryTmp = new byte[input.readInt()];
				input.readFully(queryTmp);
				this.query = new String(queryTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SearchPublicChats.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SearchPublicChats.CONSTRUCTOR);
			if (this.query == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] queryTmp = this.query.getBytes(StandardCharsets.UTF_8);
				output.writeInt(queryTmp.length);
				output.write(queryTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SearchPublicChats searchPublicChats = (SearchPublicChats) o;
			if (this.query != searchPublicChats.query) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.query == null ? 0 : this.query.hashCode();
		}
	}

	/**
	 * Searches for messages in secret chats. Returns the results in reverse
	 * chronological order. For optimal performance, the number of returned
	 * messages is chosen by TDLib.
	 * <p> Returns {@link FoundMessages FoundMessages} </p>
	**/
	public static final class SearchSecretMessages extends Function<FoundMessages> {


		/**
		 * Identifier of the chat in which to search. Specify 0 to search in all secret chats.
		**/
		public long chatId;

		/**
		 * Query to search for. If empty, searchChatMessages must be used instead.
		**/
		public String query;

		/**
		 * Offset of the first entry to return as received from the previous request; use empty string to get the first chunk of results.
		**/
		public String offset;

		/**
		 * The maximum number of messages to be returned; up to 100. For optimal performance, the number of returned messages is chosen by TDLib and can be smaller than the specified limit.
		**/
		public int limit;

		/**
		 * Additional filter for messages to search; pass null to search for all messages.
		**/
		public SearchMessagesFilter filter;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -852865892;

		/**
		 * Searches for messages in secret chats. Returns the results in reverse chronological order. For optimal performance, the number of returned messages is chosen by TDLib.
		 *
		 * <p> Returns {@link FoundMessages FoundMessages} </p>
		**/
		public SearchSecretMessages() {}

		/**
		 * Searches for messages in secret chats. Returns the results in reverse chronological order. For optimal performance, the number of returned messages is chosen by TDLib.
		 *
		 * <p> Returns {@link FoundMessages FoundMessages} </p>
		 *
		 * @param chatId Identifier of the chat in which to search. Specify 0 to search in all secret chats.
		 * @param query Query to search for. If empty, searchChatMessages must be used instead.
		 * @param offset Offset of the first entry to return as received from the previous request; use empty string to get the first chunk of results.
		 * @param limit The maximum number of messages to be returned; up to 100. For optimal performance, the number of returned messages is chosen by TDLib and can be smaller than the specified limit.
		 * @param filter Additional filter for messages to search; pass null to search for all messages.
		 *
		 * <p> Returns {@link FoundMessages FoundMessages} </p>
		**/
		public SearchSecretMessages(long chatId,
				String query,
				String offset,
				int limit,
				SearchMessagesFilter filter) {
			this.chatId = chatId;
			this.query = query;
			this.offset = offset;
			this.limit = limit;
			this.filter = filter;
		}

		/**
		 * Searches for messages in secret chats. Returns the results in reverse chronological order. For optimal performance, the number of returned messages is chosen by TDLib.
		 *
		 * <p> Returns {@link FoundMessages FoundMessages} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SearchSecretMessages(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				byte[] queryTmp = new byte[input.readInt()];
				input.readFully(queryTmp);
				this.query = new String(queryTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] offsetTmp = new byte[input.readInt()];
				input.readFully(offsetTmp);
				this.offset = new String(offsetTmp, StandardCharsets.UTF_8);
			}
			this.limit = input.readInt();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case SearchMessagesFilterEmpty.CONSTRUCTOR: this.filter = new SearchMessagesFilterEmpty(input); break;
					case SearchMessagesFilterAnimation.CONSTRUCTOR: this.filter = new SearchMessagesFilterAnimation(input); break;
					case SearchMessagesFilterAudio.CONSTRUCTOR: this.filter = new SearchMessagesFilterAudio(input); break;
					case SearchMessagesFilterDocument.CONSTRUCTOR: this.filter = new SearchMessagesFilterDocument(input); break;
					case SearchMessagesFilterPhoto.CONSTRUCTOR: this.filter = new SearchMessagesFilterPhoto(input); break;
					case SearchMessagesFilterVideo.CONSTRUCTOR: this.filter = new SearchMessagesFilterVideo(input); break;
					case SearchMessagesFilterVoiceNote.CONSTRUCTOR: this.filter = new SearchMessagesFilterVoiceNote(input); break;
					case SearchMessagesFilterPhotoAndVideo.CONSTRUCTOR: this.filter = new SearchMessagesFilterPhotoAndVideo(input); break;
					case SearchMessagesFilterUrl.CONSTRUCTOR: this.filter = new SearchMessagesFilterUrl(input); break;
					case SearchMessagesFilterChatPhoto.CONSTRUCTOR: this.filter = new SearchMessagesFilterChatPhoto(input); break;
					case SearchMessagesFilterVideoNote.CONSTRUCTOR: this.filter = new SearchMessagesFilterVideoNote(input); break;
					case SearchMessagesFilterVoiceAndVideoNote.CONSTRUCTOR: this.filter = new SearchMessagesFilterVoiceAndVideoNote(input); break;
					case SearchMessagesFilterMention.CONSTRUCTOR: this.filter = new SearchMessagesFilterMention(input); break;
					case SearchMessagesFilterUnreadMention.CONSTRUCTOR: this.filter = new SearchMessagesFilterUnreadMention(input); break;
					case SearchMessagesFilterUnreadReaction.CONSTRUCTOR: this.filter = new SearchMessagesFilterUnreadReaction(input); break;
					case SearchMessagesFilterFailedToSend.CONSTRUCTOR: this.filter = new SearchMessagesFilterFailedToSend(input); break;
					case SearchMessagesFilterPinned.CONSTRUCTOR: this.filter = new SearchMessagesFilterPinned(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SearchSecretMessages.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SearchSecretMessages.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.query == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] queryTmp = this.query.getBytes(StandardCharsets.UTF_8);
				output.writeInt(queryTmp.length);
				output.write(queryTmp);
			}
			if (this.offset == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] offsetTmp = this.offset.getBytes(StandardCharsets.UTF_8);
				output.writeInt(offsetTmp.length);
				output.write(offsetTmp);
			}
			output.writeInt(this.limit);
			if (this.filter == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.filter.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SearchSecretMessages searchSecretMessages = (SearchSecretMessages) o;
			if (this.chatId != searchSecretMessages.chatId) {
				return false;
			}
			if (this.query != searchSecretMessages.query) {
				return false;
			}
			if (this.offset != searchSecretMessages.offset) {
				return false;
			}
			if (this.limit != searchSecretMessages.limit) {
				return false;
			}
			if (!Objects.equals(this.filter, searchSecretMessages.filter)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.query == null ? 0 : this.query.hashCode());
			result = result * 31 + (this.offset == null ? 0 : this.offset.hashCode());
			result = result * 31 + (this.filter == null ? 0 : this.filter.hashCode());
			return result;
		}
	}

	/**
	 * Searches for a sticker set by its name.
	 * <p> Returns {@link StickerSet StickerSet} </p>
	**/
	public static final class SearchStickerSet extends Function<StickerSet> {


		/**
		 * Name of the sticker set.
		**/
		public String name;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1157930222;

		/**
		 * Searches for a sticker set by its name.
		 *
		 * <p> Returns {@link StickerSet StickerSet} </p>
		**/
		public SearchStickerSet() {}

		/**
		 * Searches for a sticker set by its name.
		 *
		 * <p> Returns {@link StickerSet StickerSet} </p>
		 *
		 * @param name Name of the sticker set.
		 *
		 * <p> Returns {@link StickerSet StickerSet} </p>
		**/
		public SearchStickerSet(String name) {
			this.name = name;
		}

		/**
		 * Searches for a sticker set by its name.
		 *
		 * <p> Returns {@link StickerSet StickerSet} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SearchStickerSet(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] nameTmp = new byte[input.readInt()];
				input.readFully(nameTmp);
				this.name = new String(nameTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SearchStickerSet.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SearchStickerSet.CONSTRUCTOR);
			if (this.name == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nameTmp = this.name.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nameTmp.length);
				output.write(nameTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SearchStickerSet searchStickerSet = (SearchStickerSet) o;
			if (this.name != searchStickerSet.name) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.name == null ? 0 : this.name.hashCode();
		}
	}

	/**
	 * Searches for ordinary sticker sets by looking for specified query in
	 * their title and name. Excludes installed sticker sets from the
	 * results.
	 * <p> Returns {@link StickerSets StickerSets} </p>
	**/
	public static final class SearchStickerSets extends Function<StickerSets> {


		/**
		 * Query to search for.
		**/
		public String query;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1082314629;

		/**
		 * Searches for ordinary sticker sets by looking for specified query in their title and name. Excludes installed sticker sets from the results.
		 *
		 * <p> Returns {@link StickerSets StickerSets} </p>
		**/
		public SearchStickerSets() {}

		/**
		 * Searches for ordinary sticker sets by looking for specified query in their title and name. Excludes installed sticker sets from the results.
		 *
		 * <p> Returns {@link StickerSets StickerSets} </p>
		 *
		 * @param query Query to search for.
		 *
		 * <p> Returns {@link StickerSets StickerSets} </p>
		**/
		public SearchStickerSets(String query) {
			this.query = query;
		}

		/**
		 * Searches for ordinary sticker sets by looking for specified query in their title and name. Excludes installed sticker sets from the results.
		 *
		 * <p> Returns {@link StickerSets StickerSets} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SearchStickerSets(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] queryTmp = new byte[input.readInt()];
				input.readFully(queryTmp);
				this.query = new String(queryTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SearchStickerSets.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SearchStickerSets.CONSTRUCTOR);
			if (this.query == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] queryTmp = this.query.getBytes(StandardCharsets.UTF_8);
				output.writeInt(queryTmp.length);
				output.write(queryTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SearchStickerSets searchStickerSets = (SearchStickerSets) o;
			if (this.query != searchStickerSets.query) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.query == null ? 0 : this.query.hashCode();
		}
	}

	/**
	 * Searches for stickers from public sticker sets that correspond to any
	 * of the given emoji.
	 * <p> Returns {@link Stickers Stickers} </p>
	**/
	public static final class SearchStickers extends Function<Stickers> {


		/**
		 * Type of the stickers to return.
		**/
		public StickerType stickerType;

		/**
		 * Space-separated list of emoji to search for; must be non-empty.
		**/
		public String emojis;

		/**
		 * The maximum number of stickers to be returned; 0-100.
		**/
		public int limit;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1709577973;

		/**
		 * Searches for stickers from public sticker sets that correspond to any of the given emoji.
		 *
		 * <p> Returns {@link Stickers Stickers} </p>
		**/
		public SearchStickers() {}

		/**
		 * Searches for stickers from public sticker sets that correspond to any of the given emoji.
		 *
		 * <p> Returns {@link Stickers Stickers} </p>
		 *
		 * @param stickerType Type of the stickers to return.
		 * @param emojis Space-separated list of emoji to search for; must be non-empty.
		 * @param limit The maximum number of stickers to be returned; 0-100.
		 *
		 * <p> Returns {@link Stickers Stickers} </p>
		**/
		public SearchStickers(StickerType stickerType, String emojis, int limit) {
			this.stickerType = stickerType;
			this.emojis = emojis;
			this.limit = limit;
		}

		/**
		 * Searches for stickers from public sticker sets that correspond to any of the given emoji.
		 *
		 * <p> Returns {@link Stickers Stickers} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SearchStickers(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case StickerTypeRegular.CONSTRUCTOR: this.stickerType = new StickerTypeRegular(input); break;
					case StickerTypeMask.CONSTRUCTOR: this.stickerType = new StickerTypeMask(input); break;
					case StickerTypeCustomEmoji.CONSTRUCTOR: this.stickerType = new StickerTypeCustomEmoji(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				byte[] emojisTmp = new byte[input.readInt()];
				input.readFully(emojisTmp);
				this.emojis = new String(emojisTmp, StandardCharsets.UTF_8);
			}
			this.limit = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SearchStickers.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SearchStickers.CONSTRUCTOR);
			if (this.stickerType == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.stickerType.serialize(output);
			}
			if (this.emojis == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] emojisTmp = this.emojis.getBytes(StandardCharsets.UTF_8);
				output.writeInt(emojisTmp.length);
				output.write(emojisTmp);
			}
			output.writeInt(this.limit);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SearchStickers searchStickers = (SearchStickers) o;
			if (!Objects.equals(this.stickerType, searchStickers.stickerType)) {
				return false;
			}
			if (this.emojis != searchStickers.emojis) {
				return false;
			}
			if (this.limit != searchStickers.limit) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.limit);
			result = result * 31 + (this.stickerType == null ? 0 : this.stickerType.hashCode());
			result = result * 31 + (this.emojis == null ? 0 : this.emojis.hashCode());
			return result;
		}
	}

	/**
	 * Searches a user by their phone number. Returns a 404 error if the
	 * user can&#039;t be found.
	 * <p> Returns {@link User User} </p>
	**/
	public static final class SearchUserByPhoneNumber extends Function<User> {


		/**
		 * Phone number to search for.
		**/
		public String phoneNumber;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1562236142;

		/**
		 * Searches a user by their phone number. Returns a 404 error if the user can&#039;t be found.
		 *
		 * <p> Returns {@link User User} </p>
		**/
		public SearchUserByPhoneNumber() {}

		/**
		 * Searches a user by their phone number. Returns a 404 error if the user can&#039;t be found.
		 *
		 * <p> Returns {@link User User} </p>
		 *
		 * @param phoneNumber Phone number to search for.
		 *
		 * <p> Returns {@link User User} </p>
		**/
		public SearchUserByPhoneNumber(String phoneNumber) {
			this.phoneNumber = phoneNumber;
		}

		/**
		 * Searches a user by their phone number. Returns a 404 error if the user can&#039;t be found.
		 *
		 * <p> Returns {@link User User} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SearchUserByPhoneNumber(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] phoneNumberTmp = new byte[input.readInt()];
				input.readFully(phoneNumberTmp);
				this.phoneNumber = new String(phoneNumberTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SearchUserByPhoneNumber.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SearchUserByPhoneNumber.CONSTRUCTOR);
			if (this.phoneNumber == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] phoneNumberTmp = this.phoneNumber.getBytes(StandardCharsets.UTF_8);
				output.writeInt(phoneNumberTmp.length);
				output.write(phoneNumberTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SearchUserByPhoneNumber searchUserByPhoneNumber = (SearchUserByPhoneNumber) o;
			if (this.phoneNumber != searchUserByPhoneNumber.phoneNumber) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.phoneNumber == null ? 0 : this.phoneNumber.hashCode();
		}
	}

	/**
	 * Searches a user by a token from the user&#039;s link.
	 * <p> Returns {@link User User} </p>
	**/
	public static final class SearchUserByToken extends Function<User> {


		/**
		 * Token to search for.
		**/
		public String token;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -666766282;

		/**
		 * Searches a user by a token from the user&#039;s link.
		 *
		 * <p> Returns {@link User User} </p>
		**/
		public SearchUserByToken() {}

		/**
		 * Searches a user by a token from the user&#039;s link.
		 *
		 * <p> Returns {@link User User} </p>
		 *
		 * @param token Token to search for.
		 *
		 * <p> Returns {@link User User} </p>
		**/
		public SearchUserByToken(String token) {
			this.token = token;
		}

		/**
		 * Searches a user by a token from the user&#039;s link.
		 *
		 * <p> Returns {@link User User} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SearchUserByToken(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] tokenTmp = new byte[input.readInt()];
				input.readFully(tokenTmp);
				this.token = new String(tokenTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SearchUserByToken.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SearchUserByToken.CONSTRUCTOR);
			if (this.token == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] tokenTmp = this.token.getBytes(StandardCharsets.UTF_8);
				output.writeInt(tokenTmp.length);
				output.write(tokenTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SearchUserByToken searchUserByToken = (SearchUserByToken) o;
			if (this.token != searchUserByToken.token) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.token == null ? 0 : this.token.hashCode();
		}
	}

	/**
	 * Returns information about a Web App by its short name. Returns a 404
	 * error if the Web App is not found.
	 * <p> Returns {@link FoundWebApp FoundWebApp} </p>
	**/
	public static final class SearchWebApp extends Function<FoundWebApp> {


		/**
		 * Identifier of the target bot.
		**/
		public long botUserId;

		/**
		 * Short name of the Web App.
		**/
		public String webAppShortName;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1241740747;

		/**
		 * Returns information about a Web App by its short name. Returns a 404 error if the Web App is not found.
		 *
		 * <p> Returns {@link FoundWebApp FoundWebApp} </p>
		**/
		public SearchWebApp() {}

		/**
		 * Returns information about a Web App by its short name. Returns a 404 error if the Web App is not found.
		 *
		 * <p> Returns {@link FoundWebApp FoundWebApp} </p>
		 *
		 * @param botUserId Identifier of the target bot.
		 * @param webAppShortName Short name of the Web App.
		 *
		 * <p> Returns {@link FoundWebApp FoundWebApp} </p>
		**/
		public SearchWebApp(long botUserId, String webAppShortName) {
			this.botUserId = botUserId;
			this.webAppShortName = webAppShortName;
		}

		/**
		 * Returns information about a Web App by its short name. Returns a 404 error if the Web App is not found.
		 *
		 * <p> Returns {@link FoundWebApp FoundWebApp} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SearchWebApp(DataInput input) throws IOException {
			this.botUserId = input.readLong();
			if (input.readBoolean()) {
				byte[] webAppShortNameTmp = new byte[input.readInt()];
				input.readFully(webAppShortNameTmp);
				this.webAppShortName = new String(webAppShortNameTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SearchWebApp.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SearchWebApp.CONSTRUCTOR);
			output.writeLong(this.botUserId);
			if (this.webAppShortName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] webAppShortNameTmp = this.webAppShortName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(webAppShortNameTmp.length);
				output.write(webAppShortNameTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SearchWebApp searchWebApp = (SearchWebApp) o;
			if (this.botUserId != searchWebApp.botUserId) {
				return false;
			}
			if (this.webAppShortName != searchWebApp.webAppShortName) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.botUserId);
			result = result * 31 + (this.webAppShortName == null ? 0 : this.webAppShortName.hashCode());
			return result;
		}
	}

	/**
	 * Sends Firebase Authentication SMS to the phone number of the user.
	 * Works only when the current authorization state is
	 * authorizationStateWaitCode and the server returned code of the type
	 * authenticationCodeTypeFirebaseAndroid or
	 * authenticationCodeTypeFirebaseIos.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SendAuthenticationFirebaseSms extends Function<Ok> {


		/**
		 * SafetyNet Attestation API token for the Android application, or secret from push notification for the iOS application.
		**/
		public String token;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 364994111;

		/**
		 * Sends Firebase Authentication SMS to the phone number of the user. Works only when the current authorization state is authorizationStateWaitCode and the server returned code of the type authenticationCodeTypeFirebaseAndroid or authenticationCodeTypeFirebaseIos.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SendAuthenticationFirebaseSms() {}

		/**
		 * Sends Firebase Authentication SMS to the phone number of the user. Works only when the current authorization state is authorizationStateWaitCode and the server returned code of the type authenticationCodeTypeFirebaseAndroid or authenticationCodeTypeFirebaseIos.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param token SafetyNet Attestation API token for the Android application, or secret from push notification for the iOS application.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SendAuthenticationFirebaseSms(String token) {
			this.token = token;
		}

		/**
		 * Sends Firebase Authentication SMS to the phone number of the user. Works only when the current authorization state is authorizationStateWaitCode and the server returned code of the type authenticationCodeTypeFirebaseAndroid or authenticationCodeTypeFirebaseIos.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SendAuthenticationFirebaseSms(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] tokenTmp = new byte[input.readInt()];
				input.readFully(tokenTmp);
				this.token = new String(tokenTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SendAuthenticationFirebaseSms.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SendAuthenticationFirebaseSms.CONSTRUCTOR);
			if (this.token == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] tokenTmp = this.token.getBytes(StandardCharsets.UTF_8);
				output.writeInt(tokenTmp.length);
				output.write(tokenTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SendAuthenticationFirebaseSms sendAuthenticationFirebaseSms = (SendAuthenticationFirebaseSms) o;
			if (this.token != sendAuthenticationFirebaseSms.token) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.token == null ? 0 : this.token.hashCode();
		}
	}

	/**
	 * Invites a bot to a chat (if it is not yet a member) and sends it the
	 * /start command. Bots can&#039;t be invited to a private chat other
	 * than the chat with the bot. Bots can&#039;t be invited to channels
	 * (although they can be added as admins) and secret chats. Returns the
	 * sent message.
	 * <p> Returns {@link Message Message} </p>
	**/
	public static final class SendBotStartMessage extends Function<Message> {


		/**
		 * Identifier of the bot.
		**/
		public long botUserId;

		/**
		 * Identifier of the target chat.
		**/
		public long chatId;

		/**
		 * A hidden parameter sent to the bot for deep linking purposes (https://core.telegram.org/bots#deep-linking).
		**/
		public String parameter;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1435877650;

		/**
		 * Invites a bot to a chat (if it is not yet a member) and sends it the /start command. Bots can&#039;t be invited to a private chat other than the chat with the bot. Bots can&#039;t be invited to channels (although they can be added as admins) and secret chats. Returns the sent message.
		 *
		 * <p> Returns {@link Message Message} </p>
		**/
		public SendBotStartMessage() {}

		/**
		 * Invites a bot to a chat (if it is not yet a member) and sends it the /start command. Bots can&#039;t be invited to a private chat other than the chat with the bot. Bots can&#039;t be invited to channels (although they can be added as admins) and secret chats. Returns the sent message.
		 *
		 * <p> Returns {@link Message Message} </p>
		 *
		 * @param botUserId Identifier of the bot.
		 * @param chatId Identifier of the target chat.
		 * @param parameter A hidden parameter sent to the bot for deep linking purposes (https://core.telegram.org/bots#deep-linking).
		 *
		 * <p> Returns {@link Message Message} </p>
		**/
		public SendBotStartMessage(long botUserId, long chatId, String parameter) {
			this.botUserId = botUserId;
			this.chatId = chatId;
			this.parameter = parameter;
		}

		/**
		 * Invites a bot to a chat (if it is not yet a member) and sends it the /start command. Bots can&#039;t be invited to a private chat other than the chat with the bot. Bots can&#039;t be invited to channels (although they can be added as admins) and secret chats. Returns the sent message.
		 *
		 * <p> Returns {@link Message Message} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SendBotStartMessage(DataInput input) throws IOException {
			this.botUserId = input.readLong();
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				byte[] parameterTmp = new byte[input.readInt()];
				input.readFully(parameterTmp);
				this.parameter = new String(parameterTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SendBotStartMessage.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SendBotStartMessage.CONSTRUCTOR);
			output.writeLong(this.botUserId);
			output.writeLong(this.chatId);
			if (this.parameter == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] parameterTmp = this.parameter.getBytes(StandardCharsets.UTF_8);
				output.writeInt(parameterTmp.length);
				output.write(parameterTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SendBotStartMessage sendBotStartMessage = (SendBotStartMessage) o;
			if (this.botUserId != sendBotStartMessage.botUserId) {
				return false;
			}
			if (this.chatId != sendBotStartMessage.chatId) {
				return false;
			}
			if (this.parameter != sendBotStartMessage.parameter) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.botUserId);
			result = result * 31 + (this.parameter == null ? 0 : this.parameter.hashCode());
			return result;
		}
	}

	/**
	 * Sends debug information for a call to Telegram servers.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SendCallDebugInformation extends Function<Ok> {


		/**
		 * Call identifier.
		**/
		public int callId;

		/**
		 * Debug information in application-specific format.
		**/
		public String debugInformation;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2019243839;

		/**
		 * Sends debug information for a call to Telegram servers.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SendCallDebugInformation() {}

		/**
		 * Sends debug information for a call to Telegram servers.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param callId Call identifier.
		 * @param debugInformation Debug information in application-specific format.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SendCallDebugInformation(int callId, String debugInformation) {
			this.callId = callId;
			this.debugInformation = debugInformation;
		}

		/**
		 * Sends debug information for a call to Telegram servers.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SendCallDebugInformation(DataInput input) throws IOException {
			this.callId = input.readInt();
			if (input.readBoolean()) {
				byte[] debugInformationTmp = new byte[input.readInt()];
				input.readFully(debugInformationTmp);
				this.debugInformation = new String(debugInformationTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SendCallDebugInformation.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SendCallDebugInformation.CONSTRUCTOR);
			output.writeInt(this.callId);
			if (this.debugInformation == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] debugInformationTmp = this.debugInformation.getBytes(StandardCharsets.UTF_8);
				output.writeInt(debugInformationTmp.length);
				output.write(debugInformationTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SendCallDebugInformation sendCallDebugInformation = (SendCallDebugInformation) o;
			if (this.callId != sendCallDebugInformation.callId) {
				return false;
			}
			if (this.debugInformation != sendCallDebugInformation.debugInformation) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.callId);
			result = result * 31 + (this.debugInformation == null ? 0 : this.debugInformation.hashCode());
			return result;
		}
	}

	/**
	 * Sends log file for a call to Telegram servers.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SendCallLog extends Function<Ok> {


		/**
		 * Call identifier.
		**/
		public int callId;

		/**
		 * Call log file. Only inputFileLocal and inputFileGenerated are supported.
		**/
		public InputFile logFile;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1057638353;

		/**
		 * Sends log file for a call to Telegram servers.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SendCallLog() {}

		/**
		 * Sends log file for a call to Telegram servers.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param callId Call identifier.
		 * @param logFile Call log file. Only inputFileLocal and inputFileGenerated are supported.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SendCallLog(int callId, InputFile logFile) {
			this.callId = callId;
			this.logFile = logFile;
		}

		/**
		 * Sends log file for a call to Telegram servers.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SendCallLog(DataInput input) throws IOException {
			this.callId = input.readInt();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputFileId.CONSTRUCTOR: this.logFile = new InputFileId(input); break;
					case InputFileRemote.CONSTRUCTOR: this.logFile = new InputFileRemote(input); break;
					case InputFileLocal.CONSTRUCTOR: this.logFile = new InputFileLocal(input); break;
					case InputFileGenerated.CONSTRUCTOR: this.logFile = new InputFileGenerated(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SendCallLog.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SendCallLog.CONSTRUCTOR);
			output.writeInt(this.callId);
			if (this.logFile == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.logFile.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SendCallLog sendCallLog = (SendCallLog) o;
			if (this.callId != sendCallLog.callId) {
				return false;
			}
			if (!Objects.equals(this.logFile, sendCallLog.logFile)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.callId);
			result = result * 31 + (this.logFile == null ? 0 : this.logFile.hashCode());
			return result;
		}
	}

	/**
	 * Sends a call rating.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SendCallRating extends Function<Ok> {


		/**
		 * Call identifier.
		**/
		public int callId;

		/**
		 * Call rating; 1-5.
		**/
		public int rating;

		/**
		 * An optional user comment if the rating is less than 5.
		**/
		public String comment;

		/**
		 * List of the exact types of problems with the call, specified by the user.
		**/
		public CallProblem[] problems;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1402719502;

		/**
		 * Sends a call rating.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SendCallRating() {}

		/**
		 * Sends a call rating.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param callId Call identifier.
		 * @param rating Call rating; 1-5.
		 * @param comment An optional user comment if the rating is less than 5.
		 * @param problems List of the exact types of problems with the call, specified by the user.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SendCallRating(int callId,
				int rating,
				String comment,
				CallProblem[] problems) {
			this.callId = callId;
			this.rating = rating;
			this.comment = comment;
			this.problems = problems;
		}

		/**
		 * Sends a call rating.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SendCallRating(DataInput input) throws IOException {
			this.callId = input.readInt();
			this.rating = input.readInt();
			if (input.readBoolean()) {
				byte[] commentTmp = new byte[input.readInt()];
				input.readFully(commentTmp);
				this.comment = new String(commentTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				this.problems = new CallProblem[input.readInt()];
				for (int i = 0; i < this.problems.length; i++) {
					switch(input.readInt()) {
						case CallProblemEcho.CONSTRUCTOR: this.problems[i] = new CallProblemEcho(input); break;
						case CallProblemNoise.CONSTRUCTOR: this.problems[i] = new CallProblemNoise(input); break;
						case CallProblemInterruptions.CONSTRUCTOR: this.problems[i] = new CallProblemInterruptions(input); break;
						case CallProblemDistortedSpeech.CONSTRUCTOR: this.problems[i] = new CallProblemDistortedSpeech(input); break;
						case CallProblemSilentLocal.CONSTRUCTOR: this.problems[i] = new CallProblemSilentLocal(input); break;
						case CallProblemSilentRemote.CONSTRUCTOR: this.problems[i] = new CallProblemSilentRemote(input); break;
						case CallProblemDropped.CONSTRUCTOR: this.problems[i] = new CallProblemDropped(input); break;
						case CallProblemDistortedVideo.CONSTRUCTOR: this.problems[i] = new CallProblemDistortedVideo(input); break;
						case CallProblemPixelatedVideo.CONSTRUCTOR: this.problems[i] = new CallProblemPixelatedVideo(input); break;
						default: {
							throw new UnsupportedOperationException();
						}
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SendCallRating.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SendCallRating.CONSTRUCTOR);
			output.writeInt(this.callId);
			output.writeInt(this.rating);
			if (this.comment == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] commentTmp = this.comment.getBytes(StandardCharsets.UTF_8);
				output.writeInt(commentTmp.length);
				output.write(commentTmp);
			}
			if (this.problems == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.problems.length);
				for (int i = 0; i < this.problems.length; i++) {
					this.problems[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SendCallRating sendCallRating = (SendCallRating) o;
			if (this.callId != sendCallRating.callId) {
				return false;
			}
			if (this.rating != sendCallRating.rating) {
				return false;
			}
			if (this.comment != sendCallRating.comment) {
				return false;
			}
			if (!Arrays.equals(this.problems, sendCallRating.problems)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.callId);
			result = result * 31 + (this.comment == null ? 0 : this.comment.hashCode());
			result = result * 31 + (Arrays.hashCode(this.problems));
			return result;
		}
	}

	/**
	 * Sends call signaling data.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SendCallSignalingData extends Function<Ok> {


		/**
		 * Call identifier.
		**/
		public int callId;

		/**
		 * The data.
		**/
		public byte[] data;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1412280732;

		/**
		 * Sends call signaling data.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SendCallSignalingData() {}

		/**
		 * Sends call signaling data.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param callId Call identifier.
		 * @param data The data.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SendCallSignalingData(int callId, byte[] data) {
			this.callId = callId;
			this.data = data;
		}

		/**
		 * Sends call signaling data.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SendCallSignalingData(DataInput input) throws IOException {
			this.callId = input.readInt();
			if (input.readBoolean()) {
				this.data = new byte[input.readInt()];
				input.readFully(this.data);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SendCallSignalingData.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SendCallSignalingData.CONSTRUCTOR);
			output.writeInt(this.callId);
			if (this.data == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.data.length);
				output.write(this.data);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SendCallSignalingData sendCallSignalingData = (SendCallSignalingData) o;
			if (this.callId != sendCallSignalingData.callId) {
				return false;
			}
			if (this.data != sendCallSignalingData.data) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.callId);
			result = result * 31 + (Arrays.hashCode(this.data));
			return result;
		}
	}

	/**
	 * Sends a notification about user activity in a chat.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SendChatAction extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * If not 0, a message thread identifier in which the action was performed.
		**/
		public long messageThreadId;

		/**
		 * The action description; pass null to cancel the currently active action.
		**/
		public ChatAction action;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2096947540;

		/**
		 * Sends a notification about user activity in a chat.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SendChatAction() {}

		/**
		 * Sends a notification about user activity in a chat.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param messageThreadId If not 0, a message thread identifier in which the action was performed.
		 * @param action The action description; pass null to cancel the currently active action.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SendChatAction(long chatId, long messageThreadId, ChatAction action) {
			this.chatId = chatId;
			this.messageThreadId = messageThreadId;
			this.action = action;
		}

		/**
		 * Sends a notification about user activity in a chat.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SendChatAction(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageThreadId = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ChatActionTyping.CONSTRUCTOR: this.action = new ChatActionTyping(input); break;
					case ChatActionRecordingVideo.CONSTRUCTOR: this.action = new ChatActionRecordingVideo(input); break;
					case ChatActionUploadingVideo.CONSTRUCTOR: this.action = new ChatActionUploadingVideo(input); break;
					case ChatActionRecordingVoiceNote.CONSTRUCTOR: this.action = new ChatActionRecordingVoiceNote(input); break;
					case ChatActionUploadingVoiceNote.CONSTRUCTOR: this.action = new ChatActionUploadingVoiceNote(input); break;
					case ChatActionUploadingPhoto.CONSTRUCTOR: this.action = new ChatActionUploadingPhoto(input); break;
					case ChatActionUploadingDocument.CONSTRUCTOR: this.action = new ChatActionUploadingDocument(input); break;
					case ChatActionChoosingSticker.CONSTRUCTOR: this.action = new ChatActionChoosingSticker(input); break;
					case ChatActionChoosingLocation.CONSTRUCTOR: this.action = new ChatActionChoosingLocation(input); break;
					case ChatActionChoosingContact.CONSTRUCTOR: this.action = new ChatActionChoosingContact(input); break;
					case ChatActionStartPlayingGame.CONSTRUCTOR: this.action = new ChatActionStartPlayingGame(input); break;
					case ChatActionRecordingVideoNote.CONSTRUCTOR: this.action = new ChatActionRecordingVideoNote(input); break;
					case ChatActionUploadingVideoNote.CONSTRUCTOR: this.action = new ChatActionUploadingVideoNote(input); break;
					case ChatActionWatchingAnimations.CONSTRUCTOR: this.action = new ChatActionWatchingAnimations(input); break;
					case ChatActionCancel.CONSTRUCTOR: this.action = new ChatActionCancel(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SendChatAction.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SendChatAction.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageThreadId);
			if (this.action == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.action.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SendChatAction sendChatAction = (SendChatAction) o;
			if (this.chatId != sendChatAction.chatId) {
				return false;
			}
			if (this.messageThreadId != sendChatAction.messageThreadId) {
				return false;
			}
			if (!Objects.equals(this.action, sendChatAction.action)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.action == null ? 0 : this.action.hashCode());
			return result;
		}
	}

	/**
	 * Sends a notification about a screenshot taken in a chat. Supported
	 * only in private and secret chats.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SendChatScreenshotTakenNotification extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 448399457;

		/**
		 * Sends a notification about a screenshot taken in a chat. Supported only in private and secret chats.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SendChatScreenshotTakenNotification() {}

		/**
		 * Sends a notification about a screenshot taken in a chat. Supported only in private and secret chats.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SendChatScreenshotTakenNotification(long chatId) {
			this.chatId = chatId;
		}

		/**
		 * Sends a notification about a screenshot taken in a chat. Supported only in private and secret chats.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SendChatScreenshotTakenNotification(DataInput input) throws IOException {
			this.chatId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SendChatScreenshotTakenNotification.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SendChatScreenshotTakenNotification.CONSTRUCTOR);
			output.writeLong(this.chatId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SendChatScreenshotTakenNotification sendChatScreenshotTakenNotification = (SendChatScreenshotTakenNotification) o;
			if (this.chatId != sendChatScreenshotTakenNotification.chatId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.chatId);
		}
	}

	/**
	 * Sends a custom request; for bots only.
	 * <p> Returns {@link CustomRequestResult CustomRequestResult} </p>
	**/
	public static final class SendCustomRequest extends Function<CustomRequestResult> {


		/**
		 * The method name.
		**/
		public String method;

		/**
		 * JSON-serialized method parameters.
		**/
		public String parameters;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 285045153;

		/**
		 * Sends a custom request; for bots only.
		 *
		 * <p> Returns {@link CustomRequestResult CustomRequestResult} </p>
		**/
		public SendCustomRequest() {}

		/**
		 * Sends a custom request; for bots only.
		 *
		 * <p> Returns {@link CustomRequestResult CustomRequestResult} </p>
		 *
		 * @param method The method name.
		 * @param parameters JSON-serialized method parameters.
		 *
		 * <p> Returns {@link CustomRequestResult CustomRequestResult} </p>
		**/
		public SendCustomRequest(String method, String parameters) {
			this.method = method;
			this.parameters = parameters;
		}

		/**
		 * Sends a custom request; for bots only.
		 *
		 * <p> Returns {@link CustomRequestResult CustomRequestResult} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SendCustomRequest(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] methodTmp = new byte[input.readInt()];
				input.readFully(methodTmp);
				this.method = new String(methodTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] parametersTmp = new byte[input.readInt()];
				input.readFully(parametersTmp);
				this.parameters = new String(parametersTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SendCustomRequest.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SendCustomRequest.CONSTRUCTOR);
			if (this.method == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] methodTmp = this.method.getBytes(StandardCharsets.UTF_8);
				output.writeInt(methodTmp.length);
				output.write(methodTmp);
			}
			if (this.parameters == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] parametersTmp = this.parameters.getBytes(StandardCharsets.UTF_8);
				output.writeInt(parametersTmp.length);
				output.write(parametersTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SendCustomRequest sendCustomRequest = (SendCustomRequest) o;
			if (this.method != sendCustomRequest.method) {
				return false;
			}
			if (this.parameters != sendCustomRequest.parameters) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.method == null ? 0 : this.method.hashCode();
			result = result * 31 + (this.parameters == null ? 0 : this.parameters.hashCode());
			return result;
		}
	}

	/**
	 * Sends a code to verify an email address to be added to a user&#039;s
	 * Telegram Passport.
	 * <p> Returns {@link EmailAddressAuthenticationCodeInfo
	 * EmailAddressAuthenticationCodeInfo} </p>
	**/
	public static final class SendEmailAddressVerificationCode extends Function<EmailAddressAuthenticationCodeInfo> {


		/**
		 * Email address.
		**/
		public String emailAddress;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -221621379;

		/**
		 * Sends a code to verify an email address to be added to a user&#039;s Telegram Passport.
		 *
		 * <p> Returns {@link EmailAddressAuthenticationCodeInfo EmailAddressAuthenticationCodeInfo} </p>
		**/
		public SendEmailAddressVerificationCode() {}

		/**
		 * Sends a code to verify an email address to be added to a user&#039;s Telegram Passport.
		 *
		 * <p> Returns {@link EmailAddressAuthenticationCodeInfo EmailAddressAuthenticationCodeInfo} </p>
		 *
		 * @param emailAddress Email address.
		 *
		 * <p> Returns {@link EmailAddressAuthenticationCodeInfo EmailAddressAuthenticationCodeInfo} </p>
		**/
		public SendEmailAddressVerificationCode(String emailAddress) {
			this.emailAddress = emailAddress;
		}

		/**
		 * Sends a code to verify an email address to be added to a user&#039;s Telegram Passport.
		 *
		 * <p> Returns {@link EmailAddressAuthenticationCodeInfo EmailAddressAuthenticationCodeInfo} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SendEmailAddressVerificationCode(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] emailAddressTmp = new byte[input.readInt()];
				input.readFully(emailAddressTmp);
				this.emailAddress = new String(emailAddressTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SendEmailAddressVerificationCode.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SendEmailAddressVerificationCode.CONSTRUCTOR);
			if (this.emailAddress == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] emailAddressTmp = this.emailAddress.getBytes(StandardCharsets.UTF_8);
				output.writeInt(emailAddressTmp.length);
				output.write(emailAddressTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SendEmailAddressVerificationCode sendEmailAddressVerificationCode = (SendEmailAddressVerificationCode) o;
			if (this.emailAddress != sendEmailAddressVerificationCode.emailAddress) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.emailAddress == null ? 0 : this.emailAddress.hashCode();
		}
	}

	/**
	 * Sends the result of an inline query as a message. Returns the sent
	 * message. Always clears a chat draft message.
	 * <p> Returns {@link Message Message} </p>
	**/
	public static final class SendInlineQueryResultMessage extends Function<Message> {


		/**
		 * Target chat.
		**/
		public long chatId;

		/**
		 * If not 0, a message thread identifier in which the message will be sent.
		**/
		public long messageThreadId;

		/**
		 * Identifier of a replied message; 0 if none.
		**/
		public long replyToMessageId;

		/**
		 * Options to be used to send the message; pass null to use default options.
		**/
		public MessageSendOptions options;

		/**
		 * Identifier of the inline query.
		**/
		public long queryId;

		/**
		 * Identifier of the inline result.
		**/
		public String resultId;

		/**
		 * Pass true to hide the bot, via which the message is sent. Can be used only for bots getOption(&quot;animation_search_bot_username&quot;), getOption(&quot;photo_search_bot_username&quot;), and getOption(&quot;venue_search_bot_username&quot;).
		**/
		public boolean hideViaBot;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -948639588;

		/**
		 * Sends the result of an inline query as a message. Returns the sent message. Always clears a chat draft message.
		 *
		 * <p> Returns {@link Message Message} </p>
		**/
		public SendInlineQueryResultMessage() {}

		/**
		 * Sends the result of an inline query as a message. Returns the sent message. Always clears a chat draft message.
		 *
		 * <p> Returns {@link Message Message} </p>
		 *
		 * @param chatId Target chat.
		 * @param messageThreadId If not 0, a message thread identifier in which the message will be sent.
		 * @param replyToMessageId Identifier of a replied message; 0 if none.
		 * @param options Options to be used to send the message; pass null to use default options.
		 * @param queryId Identifier of the inline query.
		 * @param resultId Identifier of the inline result.
		 * @param hideViaBot Pass true to hide the bot, via which the message is sent. Can be used only for bots getOption(&quot;animation_search_bot_username&quot;), getOption(&quot;photo_search_bot_username&quot;), and getOption(&quot;venue_search_bot_username&quot;).
		 *
		 * <p> Returns {@link Message Message} </p>
		**/
		public SendInlineQueryResultMessage(long chatId,
				long messageThreadId,
				long replyToMessageId,
				MessageSendOptions options,
				long queryId,
				String resultId,
				boolean hideViaBot) {
			this.chatId = chatId;
			this.messageThreadId = messageThreadId;
			this.replyToMessageId = replyToMessageId;
			this.options = options;
			this.queryId = queryId;
			this.resultId = resultId;
			this.hideViaBot = hideViaBot;
		}

		/**
		 * Sends the result of an inline query as a message. Returns the sent message. Always clears a chat draft message.
		 *
		 * <p> Returns {@link Message Message} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SendInlineQueryResultMessage(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageThreadId = input.readLong();
			this.replyToMessageId = input.readLong();
			if (input.readBoolean()) {
				if (MessageSendOptions.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.options = new MessageSendOptions(input);
			}
			this.queryId = input.readLong();
			if (input.readBoolean()) {
				byte[] resultIdTmp = new byte[input.readInt()];
				input.readFully(resultIdTmp);
				this.resultId = new String(resultIdTmp, StandardCharsets.UTF_8);
			}
			this.hideViaBot = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SendInlineQueryResultMessage.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SendInlineQueryResultMessage.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageThreadId);
			output.writeLong(this.replyToMessageId);
			if (this.options == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.options.serialize(output);
			}
			output.writeLong(this.queryId);
			if (this.resultId == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] resultIdTmp = this.resultId.getBytes(StandardCharsets.UTF_8);
				output.writeInt(resultIdTmp.length);
				output.write(resultIdTmp);
			}
			output.writeBoolean(this.hideViaBot);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SendInlineQueryResultMessage sendInlineQueryResultMessage = (SendInlineQueryResultMessage) o;
			if (this.chatId != sendInlineQueryResultMessage.chatId) {
				return false;
			}
			if (this.messageThreadId != sendInlineQueryResultMessage.messageThreadId) {
				return false;
			}
			if (this.replyToMessageId != sendInlineQueryResultMessage.replyToMessageId) {
				return false;
			}
			if (!Objects.equals(this.options, sendInlineQueryResultMessage.options)) {
				return false;
			}
			if (this.queryId != sendInlineQueryResultMessage.queryId) {
				return false;
			}
			if (this.resultId != sendInlineQueryResultMessage.resultId) {
				return false;
			}
			if (this.hideViaBot != sendInlineQueryResultMessage.hideViaBot) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.options == null ? 0 : this.options.hashCode());
			result = result * 31 + (this.resultId == null ? 0 : this.resultId.hashCode());
			return result;
		}
	}

	/**
	 * Sends a message. Returns the sent message.
	 * <p> Returns {@link Message Message} </p>
	**/
	public static final class SendMessage extends Function<Message> {


		/**
		 * Target chat.
		**/
		public long chatId;

		/**
		 * If not 0, a message thread identifier in which the message will be sent.
		**/
		public long messageThreadId;

		/**
		 * Identifier of the replied message; 0 if none.
		**/
		public long replyToMessageId;

		/**
		 * Options to be used to send the message; pass null to use default options.
		**/
		public MessageSendOptions options;

		/**
		 * Markup for replying to the message; pass null if none; for bots only.
		**/
		public ReplyMarkup replyMarkup;

		/**
		 * The content of the message to be sent.
		**/
		public InputMessageContent inputMessageContent;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 960453021;

		/**
		 * Sends a message. Returns the sent message.
		 *
		 * <p> Returns {@link Message Message} </p>
		**/
		public SendMessage() {}

		/**
		 * Sends a message. Returns the sent message.
		 *
		 * <p> Returns {@link Message Message} </p>
		 *
		 * @param chatId Target chat.
		 * @param messageThreadId If not 0, a message thread identifier in which the message will be sent.
		 * @param replyToMessageId Identifier of the replied message; 0 if none.
		 * @param options Options to be used to send the message; pass null to use default options.
		 * @param replyMarkup Markup for replying to the message; pass null if none; for bots only.
		 * @param inputMessageContent The content of the message to be sent.
		 *
		 * <p> Returns {@link Message Message} </p>
		**/
		public SendMessage(long chatId,
				long messageThreadId,
				long replyToMessageId,
				MessageSendOptions options,
				ReplyMarkup replyMarkup,
				InputMessageContent inputMessageContent) {
			this.chatId = chatId;
			this.messageThreadId = messageThreadId;
			this.replyToMessageId = replyToMessageId;
			this.options = options;
			this.replyMarkup = replyMarkup;
			this.inputMessageContent = inputMessageContent;
		}

		/**
		 * Sends a message. Returns the sent message.
		 *
		 * <p> Returns {@link Message Message} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SendMessage(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageThreadId = input.readLong();
			this.replyToMessageId = input.readLong();
			if (input.readBoolean()) {
				if (MessageSendOptions.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.options = new MessageSendOptions(input);
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ReplyMarkupRemoveKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupRemoveKeyboard(input); break;
					case ReplyMarkupForceReply.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupForceReply(input); break;
					case ReplyMarkupShowKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupShowKeyboard(input); break;
					case ReplyMarkupInlineKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupInlineKeyboard(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputMessageText.CONSTRUCTOR: this.inputMessageContent = new InputMessageText(input); break;
					case InputMessageAnimation.CONSTRUCTOR: this.inputMessageContent = new InputMessageAnimation(input); break;
					case InputMessageAudio.CONSTRUCTOR: this.inputMessageContent = new InputMessageAudio(input); break;
					case InputMessageDocument.CONSTRUCTOR: this.inputMessageContent = new InputMessageDocument(input); break;
					case InputMessagePhoto.CONSTRUCTOR: this.inputMessageContent = new InputMessagePhoto(input); break;
					case InputMessageSticker.CONSTRUCTOR: this.inputMessageContent = new InputMessageSticker(input); break;
					case InputMessageVideo.CONSTRUCTOR: this.inputMessageContent = new InputMessageVideo(input); break;
					case InputMessageVideoNote.CONSTRUCTOR: this.inputMessageContent = new InputMessageVideoNote(input); break;
					case InputMessageVoiceNote.CONSTRUCTOR: this.inputMessageContent = new InputMessageVoiceNote(input); break;
					case InputMessageLocation.CONSTRUCTOR: this.inputMessageContent = new InputMessageLocation(input); break;
					case InputMessageVenue.CONSTRUCTOR: this.inputMessageContent = new InputMessageVenue(input); break;
					case InputMessageContact.CONSTRUCTOR: this.inputMessageContent = new InputMessageContact(input); break;
					case InputMessageDice.CONSTRUCTOR: this.inputMessageContent = new InputMessageDice(input); break;
					case InputMessageGame.CONSTRUCTOR: this.inputMessageContent = new InputMessageGame(input); break;
					case InputMessageInvoice.CONSTRUCTOR: this.inputMessageContent = new InputMessageInvoice(input); break;
					case InputMessagePoll.CONSTRUCTOR: this.inputMessageContent = new InputMessagePoll(input); break;
					case InputMessageForwarded.CONSTRUCTOR: this.inputMessageContent = new InputMessageForwarded(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SendMessage.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SendMessage.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageThreadId);
			output.writeLong(this.replyToMessageId);
			if (this.options == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.options.serialize(output);
			}
			if (this.replyMarkup == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.replyMarkup.serialize(output);
			}
			if (this.inputMessageContent == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.inputMessageContent.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SendMessage sendMessage = (SendMessage) o;
			if (this.chatId != sendMessage.chatId) {
				return false;
			}
			if (this.messageThreadId != sendMessage.messageThreadId) {
				return false;
			}
			if (this.replyToMessageId != sendMessage.replyToMessageId) {
				return false;
			}
			if (!Objects.equals(this.options, sendMessage.options)) {
				return false;
			}
			if (!Objects.equals(this.replyMarkup, sendMessage.replyMarkup)) {
				return false;
			}
			if (!Objects.equals(this.inputMessageContent, sendMessage.inputMessageContent)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.options == null ? 0 : this.options.hashCode());
			result = result * 31 + (this.replyMarkup == null ? 0 : this.replyMarkup.hashCode());
			result = result * 31 + (this.inputMessageContent == null ? 0 : this.inputMessageContent.hashCode());
			return result;
		}
	}

	/**
	 * Sends 2-10 messages grouped together into an album. Currently, only
	 * audio, document, photo and video messages can be grouped into an
	 * album. Documents and audio files can be only grouped in an album with
	 * messages of the same type. Returns sent messages.
	 * <p> Returns {@link Messages Messages} </p>
	**/
	public static final class SendMessageAlbum extends Function<Messages> {


		/**
		 * Target chat.
		**/
		public long chatId;

		/**
		 * If not 0, a message thread identifier in which the messages will be sent.
		**/
		public long messageThreadId;

		/**
		 * Identifier of a replied message; 0 if none.
		**/
		public long replyToMessageId;

		/**
		 * Options to be used to send the messages; pass null to use default options.
		**/
		public MessageSendOptions options;

		/**
		 * Contents of messages to be sent. At most 10 messages can be added to an album.
		**/
		public InputMessageContent[] inputMessageContents;

		/**
		 * Pass true to get fake messages instead of actually sending them.
		**/
		public boolean onlyPreview;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1639797862;

		/**
		 * Sends 2-10 messages grouped together into an album. Currently, only audio, document, photo and video messages can be grouped into an album. Documents and audio files can be only grouped in an album with messages of the same type. Returns sent messages.
		 *
		 * <p> Returns {@link Messages Messages} </p>
		**/
		public SendMessageAlbum() {}

		/**
		 * Sends 2-10 messages grouped together into an album. Currently, only audio, document, photo and video messages can be grouped into an album. Documents and audio files can be only grouped in an album with messages of the same type. Returns sent messages.
		 *
		 * <p> Returns {@link Messages Messages} </p>
		 *
		 * @param chatId Target chat.
		 * @param messageThreadId If not 0, a message thread identifier in which the messages will be sent.
		 * @param replyToMessageId Identifier of a replied message; 0 if none.
		 * @param options Options to be used to send the messages; pass null to use default options.
		 * @param inputMessageContents Contents of messages to be sent. At most 10 messages can be added to an album.
		 * @param onlyPreview Pass true to get fake messages instead of actually sending them.
		 *
		 * <p> Returns {@link Messages Messages} </p>
		**/
		public SendMessageAlbum(long chatId,
				long messageThreadId,
				long replyToMessageId,
				MessageSendOptions options,
				InputMessageContent[] inputMessageContents,
				boolean onlyPreview) {
			this.chatId = chatId;
			this.messageThreadId = messageThreadId;
			this.replyToMessageId = replyToMessageId;
			this.options = options;
			this.inputMessageContents = inputMessageContents;
			this.onlyPreview = onlyPreview;
		}

		/**
		 * Sends 2-10 messages grouped together into an album. Currently, only audio, document, photo and video messages can be grouped into an album. Documents and audio files can be only grouped in an album with messages of the same type. Returns sent messages.
		 *
		 * <p> Returns {@link Messages Messages} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SendMessageAlbum(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageThreadId = input.readLong();
			this.replyToMessageId = input.readLong();
			if (input.readBoolean()) {
				if (MessageSendOptions.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.options = new MessageSendOptions(input);
			}
			if (input.readBoolean()) {
				this.inputMessageContents = new InputMessageContent[input.readInt()];
				for (int i = 0; i < this.inputMessageContents.length; i++) {
					switch(input.readInt()) {
						case InputMessageText.CONSTRUCTOR: this.inputMessageContents[i] = new InputMessageText(input); break;
						case InputMessageAnimation.CONSTRUCTOR: this.inputMessageContents[i] = new InputMessageAnimation(input); break;
						case InputMessageAudio.CONSTRUCTOR: this.inputMessageContents[i] = new InputMessageAudio(input); break;
						case InputMessageDocument.CONSTRUCTOR: this.inputMessageContents[i] = new InputMessageDocument(input); break;
						case InputMessagePhoto.CONSTRUCTOR: this.inputMessageContents[i] = new InputMessagePhoto(input); break;
						case InputMessageSticker.CONSTRUCTOR: this.inputMessageContents[i] = new InputMessageSticker(input); break;
						case InputMessageVideo.CONSTRUCTOR: this.inputMessageContents[i] = new InputMessageVideo(input); break;
						case InputMessageVideoNote.CONSTRUCTOR: this.inputMessageContents[i] = new InputMessageVideoNote(input); break;
						case InputMessageVoiceNote.CONSTRUCTOR: this.inputMessageContents[i] = new InputMessageVoiceNote(input); break;
						case InputMessageLocation.CONSTRUCTOR: this.inputMessageContents[i] = new InputMessageLocation(input); break;
						case InputMessageVenue.CONSTRUCTOR: this.inputMessageContents[i] = new InputMessageVenue(input); break;
						case InputMessageContact.CONSTRUCTOR: this.inputMessageContents[i] = new InputMessageContact(input); break;
						case InputMessageDice.CONSTRUCTOR: this.inputMessageContents[i] = new InputMessageDice(input); break;
						case InputMessageGame.CONSTRUCTOR: this.inputMessageContents[i] = new InputMessageGame(input); break;
						case InputMessageInvoice.CONSTRUCTOR: this.inputMessageContents[i] = new InputMessageInvoice(input); break;
						case InputMessagePoll.CONSTRUCTOR: this.inputMessageContents[i] = new InputMessagePoll(input); break;
						case InputMessageForwarded.CONSTRUCTOR: this.inputMessageContents[i] = new InputMessageForwarded(input); break;
						default: {
							throw new UnsupportedOperationException();
						}
					}
				}
			}
			this.onlyPreview = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SendMessageAlbum.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SendMessageAlbum.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageThreadId);
			output.writeLong(this.replyToMessageId);
			if (this.options == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.options.serialize(output);
			}
			if (this.inputMessageContents == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.inputMessageContents.length);
				for (int i = 0; i < this.inputMessageContents.length; i++) {
					this.inputMessageContents[i].serialize(output);
				}
			}
			output.writeBoolean(this.onlyPreview);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SendMessageAlbum sendMessageAlbum = (SendMessageAlbum) o;
			if (this.chatId != sendMessageAlbum.chatId) {
				return false;
			}
			if (this.messageThreadId != sendMessageAlbum.messageThreadId) {
				return false;
			}
			if (this.replyToMessageId != sendMessageAlbum.replyToMessageId) {
				return false;
			}
			if (!Objects.equals(this.options, sendMessageAlbum.options)) {
				return false;
			}
			if (!Arrays.equals(this.inputMessageContents, sendMessageAlbum.inputMessageContents)) {
				return false;
			}
			if (this.onlyPreview != sendMessageAlbum.onlyPreview) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.options == null ? 0 : this.options.hashCode());
			result = result * 31 + (Arrays.hashCode(this.inputMessageContents));
			return result;
		}
	}

	/**
	 * Sends a Telegram Passport authorization form, effectively sharing
	 * data with the service. This method must be called after
	 * getPassportAuthorizationFormAvailableElements if some previously
	 * available elements are going to be reused.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SendPassportAuthorizationForm extends Function<Ok> {


		/**
		 * Authorization form identifier.
		**/
		public int authorizationFormId;

		/**
		 * Types of Telegram Passport elements chosen by user to complete the authorization form.
		**/
		public PassportElementType[] types;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 652160701;

		/**
		 * Sends a Telegram Passport authorization form, effectively sharing data with the service. This method must be called after getPassportAuthorizationFormAvailableElements if some previously available elements are going to be reused.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SendPassportAuthorizationForm() {}

		/**
		 * Sends a Telegram Passport authorization form, effectively sharing data with the service. This method must be called after getPassportAuthorizationFormAvailableElements if some previously available elements are going to be reused.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param authorizationFormId Authorization form identifier.
		 * @param types Types of Telegram Passport elements chosen by user to complete the authorization form.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SendPassportAuthorizationForm(int authorizationFormId, PassportElementType[] types) {
			this.authorizationFormId = authorizationFormId;
			this.types = types;
		}

		/**
		 * Sends a Telegram Passport authorization form, effectively sharing data with the service. This method must be called after getPassportAuthorizationFormAvailableElements if some previously available elements are going to be reused.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SendPassportAuthorizationForm(DataInput input) throws IOException {
			this.authorizationFormId = input.readInt();
			if (input.readBoolean()) {
				this.types = new PassportElementType[input.readInt()];
				for (int i = 0; i < this.types.length; i++) {
					switch(input.readInt()) {
						case PassportElementTypePersonalDetails.CONSTRUCTOR: this.types[i] = new PassportElementTypePersonalDetails(input); break;
						case PassportElementTypePassport.CONSTRUCTOR: this.types[i] = new PassportElementTypePassport(input); break;
						case PassportElementTypeDriverLicense.CONSTRUCTOR: this.types[i] = new PassportElementTypeDriverLicense(input); break;
						case PassportElementTypeIdentityCard.CONSTRUCTOR: this.types[i] = new PassportElementTypeIdentityCard(input); break;
						case PassportElementTypeInternalPassport.CONSTRUCTOR: this.types[i] = new PassportElementTypeInternalPassport(input); break;
						case PassportElementTypeAddress.CONSTRUCTOR: this.types[i] = new PassportElementTypeAddress(input); break;
						case PassportElementTypeUtilityBill.CONSTRUCTOR: this.types[i] = new PassportElementTypeUtilityBill(input); break;
						case PassportElementTypeBankStatement.CONSTRUCTOR: this.types[i] = new PassportElementTypeBankStatement(input); break;
						case PassportElementTypeRentalAgreement.CONSTRUCTOR: this.types[i] = new PassportElementTypeRentalAgreement(input); break;
						case PassportElementTypePassportRegistration.CONSTRUCTOR: this.types[i] = new PassportElementTypePassportRegistration(input); break;
						case PassportElementTypeTemporaryRegistration.CONSTRUCTOR: this.types[i] = new PassportElementTypeTemporaryRegistration(input); break;
						case PassportElementTypePhoneNumber.CONSTRUCTOR: this.types[i] = new PassportElementTypePhoneNumber(input); break;
						case PassportElementTypeEmailAddress.CONSTRUCTOR: this.types[i] = new PassportElementTypeEmailAddress(input); break;
						default: {
							throw new UnsupportedOperationException();
						}
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SendPassportAuthorizationForm.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SendPassportAuthorizationForm.CONSTRUCTOR);
			output.writeInt(this.authorizationFormId);
			if (this.types == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.types.length);
				for (int i = 0; i < this.types.length; i++) {
					this.types[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SendPassportAuthorizationForm sendPassportAuthorizationForm = (SendPassportAuthorizationForm) o;
			if (this.authorizationFormId != sendPassportAuthorizationForm.authorizationFormId) {
				return false;
			}
			if (!Arrays.equals(this.types, sendPassportAuthorizationForm.types)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.authorizationFormId);
			result = result * 31 + (Arrays.hashCode(this.types));
			return result;
		}
	}

	/**
	 * Sends a filled-out payment form to the bot for final verification.
	 * <p> Returns {@link PaymentResult PaymentResult} </p>
	**/
	public static final class SendPaymentForm extends Function<PaymentResult> {


		/**
		 * The invoice.
		**/
		public InputInvoice inputInvoice;

		/**
		 * Payment form identifier returned by getPaymentForm.
		**/
		public long paymentFormId;

		/**
		 * Identifier returned by validateOrderInfo, or an empty string.
		**/
		public String orderInfoId;

		/**
		 * Identifier of a chosen shipping option, if applicable.
		**/
		public String shippingOptionId;

		/**
		 * The credentials chosen by user for payment.
		**/
		public InputCredentials credentials;

		/**
		 * Chosen by the user amount of tip in the smallest units of the currency.
		**/
		public long tipAmount;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -965855094;

		/**
		 * Sends a filled-out payment form to the bot for final verification.
		 *
		 * <p> Returns {@link PaymentResult PaymentResult} </p>
		**/
		public SendPaymentForm() {}

		/**
		 * Sends a filled-out payment form to the bot for final verification.
		 *
		 * <p> Returns {@link PaymentResult PaymentResult} </p>
		 *
		 * @param inputInvoice The invoice.
		 * @param paymentFormId Payment form identifier returned by getPaymentForm.
		 * @param orderInfoId Identifier returned by validateOrderInfo, or an empty string.
		 * @param shippingOptionId Identifier of a chosen shipping option, if applicable.
		 * @param credentials The credentials chosen by user for payment.
		 * @param tipAmount Chosen by the user amount of tip in the smallest units of the currency.
		 *
		 * <p> Returns {@link PaymentResult PaymentResult} </p>
		**/
		public SendPaymentForm(InputInvoice inputInvoice,
				long paymentFormId,
				String orderInfoId,
				String shippingOptionId,
				InputCredentials credentials,
				long tipAmount) {
			this.inputInvoice = inputInvoice;
			this.paymentFormId = paymentFormId;
			this.orderInfoId = orderInfoId;
			this.shippingOptionId = shippingOptionId;
			this.credentials = credentials;
			this.tipAmount = tipAmount;
		}

		/**
		 * Sends a filled-out payment form to the bot for final verification.
		 *
		 * <p> Returns {@link PaymentResult PaymentResult} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SendPaymentForm(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputInvoiceMessage.CONSTRUCTOR: this.inputInvoice = new InputInvoiceMessage(input); break;
					case InputInvoiceName.CONSTRUCTOR: this.inputInvoice = new InputInvoiceName(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.paymentFormId = input.readLong();
			if (input.readBoolean()) {
				byte[] orderInfoIdTmp = new byte[input.readInt()];
				input.readFully(orderInfoIdTmp);
				this.orderInfoId = new String(orderInfoIdTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] shippingOptionIdTmp = new byte[input.readInt()];
				input.readFully(shippingOptionIdTmp);
				this.shippingOptionId = new String(shippingOptionIdTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputCredentialsSaved.CONSTRUCTOR: this.credentials = new InputCredentialsSaved(input); break;
					case InputCredentialsNew.CONSTRUCTOR: this.credentials = new InputCredentialsNew(input); break;
					case InputCredentialsApplePay.CONSTRUCTOR: this.credentials = new InputCredentialsApplePay(input); break;
					case InputCredentialsGooglePay.CONSTRUCTOR: this.credentials = new InputCredentialsGooglePay(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.tipAmount = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SendPaymentForm.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SendPaymentForm.CONSTRUCTOR);
			if (this.inputInvoice == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.inputInvoice.serialize(output);
			}
			output.writeLong(this.paymentFormId);
			if (this.orderInfoId == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] orderInfoIdTmp = this.orderInfoId.getBytes(StandardCharsets.UTF_8);
				output.writeInt(orderInfoIdTmp.length);
				output.write(orderInfoIdTmp);
			}
			if (this.shippingOptionId == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] shippingOptionIdTmp = this.shippingOptionId.getBytes(StandardCharsets.UTF_8);
				output.writeInt(shippingOptionIdTmp.length);
				output.write(shippingOptionIdTmp);
			}
			if (this.credentials == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.credentials.serialize(output);
			}
			output.writeLong(this.tipAmount);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SendPaymentForm sendPaymentForm = (SendPaymentForm) o;
			if (!Objects.equals(this.inputInvoice, sendPaymentForm.inputInvoice)) {
				return false;
			}
			if (this.paymentFormId != sendPaymentForm.paymentFormId) {
				return false;
			}
			if (this.orderInfoId != sendPaymentForm.orderInfoId) {
				return false;
			}
			if (this.shippingOptionId != sendPaymentForm.shippingOptionId) {
				return false;
			}
			if (!Objects.equals(this.credentials, sendPaymentForm.credentials)) {
				return false;
			}
			if (this.tipAmount != sendPaymentForm.tipAmount) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.paymentFormId);
			result = result * 31 + (this.inputInvoice == null ? 0 : this.inputInvoice.hashCode());
			result = result * 31 + (this.orderInfoId == null ? 0 : this.orderInfoId.hashCode());
			result = result * 31 + (this.shippingOptionId == null ? 0 : this.shippingOptionId.hashCode());
			result = result * 31 + (this.credentials == null ? 0 : this.credentials.hashCode());
			return result;
		}
	}

	/**
	 * Sends phone number confirmation code to handle links of the type
	 * internalLinkTypePhoneNumberConfirmation.
	 * <p> Returns {@link AuthenticationCodeInfo AuthenticationCodeInfo} </p>
	**/
	public static final class SendPhoneNumberConfirmationCode extends Function<AuthenticationCodeInfo> {


		/**
		 * Hash value from the link.
		**/
		public String hash;

		/**
		 * Phone number value from the link.
		**/
		public String phoneNumber;

		/**
		 * Settings for the authentication of the user&#039;s phone number; pass null to use default settings.
		**/
		public PhoneNumberAuthenticationSettings settings;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1901171495;

		/**
		 * Sends phone number confirmation code to handle links of the type internalLinkTypePhoneNumberConfirmation.
		 *
		 * <p> Returns {@link AuthenticationCodeInfo AuthenticationCodeInfo} </p>
		**/
		public SendPhoneNumberConfirmationCode() {}

		/**
		 * Sends phone number confirmation code to handle links of the type internalLinkTypePhoneNumberConfirmation.
		 *
		 * <p> Returns {@link AuthenticationCodeInfo AuthenticationCodeInfo} </p>
		 *
		 * @param hash Hash value from the link.
		 * @param phoneNumber Phone number value from the link.
		 * @param settings Settings for the authentication of the user&#039;s phone number; pass null to use default settings.
		 *
		 * <p> Returns {@link AuthenticationCodeInfo AuthenticationCodeInfo} </p>
		**/
		public SendPhoneNumberConfirmationCode(String hash,
				String phoneNumber,
				PhoneNumberAuthenticationSettings settings) {
			this.hash = hash;
			this.phoneNumber = phoneNumber;
			this.settings = settings;
		}

		/**
		 * Sends phone number confirmation code to handle links of the type internalLinkTypePhoneNumberConfirmation.
		 *
		 * <p> Returns {@link AuthenticationCodeInfo AuthenticationCodeInfo} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SendPhoneNumberConfirmationCode(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] hashTmp = new byte[input.readInt()];
				input.readFully(hashTmp);
				this.hash = new String(hashTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] phoneNumberTmp = new byte[input.readInt()];
				input.readFully(phoneNumberTmp);
				this.phoneNumber = new String(phoneNumberTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (PhoneNumberAuthenticationSettings.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.settings = new PhoneNumberAuthenticationSettings(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SendPhoneNumberConfirmationCode.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SendPhoneNumberConfirmationCode.CONSTRUCTOR);
			if (this.hash == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] hashTmp = this.hash.getBytes(StandardCharsets.UTF_8);
				output.writeInt(hashTmp.length);
				output.write(hashTmp);
			}
			if (this.phoneNumber == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] phoneNumberTmp = this.phoneNumber.getBytes(StandardCharsets.UTF_8);
				output.writeInt(phoneNumberTmp.length);
				output.write(phoneNumberTmp);
			}
			if (this.settings == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.settings.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SendPhoneNumberConfirmationCode sendPhoneNumberConfirmationCode = (SendPhoneNumberConfirmationCode) o;
			if (this.hash != sendPhoneNumberConfirmationCode.hash) {
				return false;
			}
			if (this.phoneNumber != sendPhoneNumberConfirmationCode.phoneNumber) {
				return false;
			}
			if (!Objects.equals(this.settings, sendPhoneNumberConfirmationCode.settings)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.hash == null ? 0 : this.hash.hashCode();
			result = result * 31 + (this.phoneNumber == null ? 0 : this.phoneNumber.hashCode());
			result = result * 31 + (this.settings == null ? 0 : this.settings.hashCode());
			return result;
		}
	}

	/**
	 * Sends a code to verify a phone number to be added to a user&#039;s
	 * Telegram Passport.
	 * <p> Returns {@link AuthenticationCodeInfo AuthenticationCodeInfo} </p>
	**/
	public static final class SendPhoneNumberVerificationCode extends Function<AuthenticationCodeInfo> {


		/**
		 * The phone number of the user, in international format.
		**/
		public String phoneNumber;

		/**
		 * Settings for the authentication of the user&#039;s phone number; pass null to use default settings.
		**/
		public PhoneNumberAuthenticationSettings settings;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2081689035;

		/**
		 * Sends a code to verify a phone number to be added to a user&#039;s Telegram Passport.
		 *
		 * <p> Returns {@link AuthenticationCodeInfo AuthenticationCodeInfo} </p>
		**/
		public SendPhoneNumberVerificationCode() {}

		/**
		 * Sends a code to verify a phone number to be added to a user&#039;s Telegram Passport.
		 *
		 * <p> Returns {@link AuthenticationCodeInfo AuthenticationCodeInfo} </p>
		 *
		 * @param phoneNumber The phone number of the user, in international format.
		 * @param settings Settings for the authentication of the user&#039;s phone number; pass null to use default settings.
		 *
		 * <p> Returns {@link AuthenticationCodeInfo AuthenticationCodeInfo} </p>
		**/
		public SendPhoneNumberVerificationCode(String phoneNumber,
				PhoneNumberAuthenticationSettings settings) {
			this.phoneNumber = phoneNumber;
			this.settings = settings;
		}

		/**
		 * Sends a code to verify a phone number to be added to a user&#039;s Telegram Passport.
		 *
		 * <p> Returns {@link AuthenticationCodeInfo AuthenticationCodeInfo} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SendPhoneNumberVerificationCode(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] phoneNumberTmp = new byte[input.readInt()];
				input.readFully(phoneNumberTmp);
				this.phoneNumber = new String(phoneNumberTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (PhoneNumberAuthenticationSettings.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.settings = new PhoneNumberAuthenticationSettings(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SendPhoneNumberVerificationCode.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SendPhoneNumberVerificationCode.CONSTRUCTOR);
			if (this.phoneNumber == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] phoneNumberTmp = this.phoneNumber.getBytes(StandardCharsets.UTF_8);
				output.writeInt(phoneNumberTmp.length);
				output.write(phoneNumberTmp);
			}
			if (this.settings == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.settings.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SendPhoneNumberVerificationCode sendPhoneNumberVerificationCode = (SendPhoneNumberVerificationCode) o;
			if (this.phoneNumber != sendPhoneNumberVerificationCode.phoneNumber) {
				return false;
			}
			if (!Objects.equals(this.settings, sendPhoneNumberVerificationCode.settings)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.phoneNumber == null ? 0 : this.phoneNumber.hashCode();
			result = result * 31 + (this.settings == null ? 0 : this.settings.hashCode());
			return result;
		}
	}

	/**
	 * Sends data received from a keyboardButtonTypeWebApp Web App to a bot.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SendWebAppData extends Function<Ok> {


		/**
		 * Identifier of the target bot.
		**/
		public long botUserId;

		/**
		 * Text of the keyboardButtonTypeWebApp button, which opened the Web App.
		**/
		public String buttonText;

		/**
		 * The data.
		**/
		public String data;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1423978996;

		/**
		 * Sends data received from a keyboardButtonTypeWebApp Web App to a bot.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SendWebAppData() {}

		/**
		 * Sends data received from a keyboardButtonTypeWebApp Web App to a bot.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param botUserId Identifier of the target bot.
		 * @param buttonText Text of the keyboardButtonTypeWebApp button, which opened the Web App.
		 * @param data The data.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SendWebAppData(long botUserId, String buttonText, String data) {
			this.botUserId = botUserId;
			this.buttonText = buttonText;
			this.data = data;
		}

		/**
		 * Sends data received from a keyboardButtonTypeWebApp Web App to a bot.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SendWebAppData(DataInput input) throws IOException {
			this.botUserId = input.readLong();
			if (input.readBoolean()) {
				byte[] buttonTextTmp = new byte[input.readInt()];
				input.readFully(buttonTextTmp);
				this.buttonText = new String(buttonTextTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] dataTmp = new byte[input.readInt()];
				input.readFully(dataTmp);
				this.data = new String(dataTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SendWebAppData.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SendWebAppData.CONSTRUCTOR);
			output.writeLong(this.botUserId);
			if (this.buttonText == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] buttonTextTmp = this.buttonText.getBytes(StandardCharsets.UTF_8);
				output.writeInt(buttonTextTmp.length);
				output.write(buttonTextTmp);
			}
			if (this.data == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] dataTmp = this.data.getBytes(StandardCharsets.UTF_8);
				output.writeInt(dataTmp.length);
				output.write(dataTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SendWebAppData sendWebAppData = (SendWebAppData) o;
			if (this.botUserId != sendWebAppData.botUserId) {
				return false;
			}
			if (this.buttonText != sendWebAppData.buttonText) {
				return false;
			}
			if (this.data != sendWebAppData.data) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.botUserId);
			result = result * 31 + (this.buttonText == null ? 0 : this.buttonText.hashCode());
			result = result * 31 + (this.data == null ? 0 : this.data.hashCode());
			return result;
		}
	}

	/**
	 * Changes the period of inactivity after which the account of the
	 * current user will automatically be deleted.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetAccountTtl extends Function<Ok> {


		/**
		 * New account TTL.
		**/
		public AccountTtl ttl;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 701389032;

		/**
		 * Changes the period of inactivity after which the account of the current user will automatically be deleted.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetAccountTtl() {}

		/**
		 * Changes the period of inactivity after which the account of the current user will automatically be deleted.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param ttl New account TTL.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetAccountTtl(AccountTtl ttl) {
			this.ttl = ttl;
		}

		/**
		 * Changes the period of inactivity after which the account of the current user will automatically be deleted.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetAccountTtl(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (AccountTtl.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.ttl = new AccountTtl(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetAccountTtl.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetAccountTtl.CONSTRUCTOR);
			if (this.ttl == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.ttl.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetAccountTtl setAccountTtl = (SetAccountTtl) o;
			if (!Objects.equals(this.ttl, setAccountTtl.ttl)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.ttl == null ? 0 : this.ttl.hashCode();
		}
	}

	/**
	 * Succeeds after a specified amount of time has passed. Can be called
	 * before initialization.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetAlarm extends Function<Ok> {


		/**
		 * Number of seconds before the function returns.
		**/
		public double seconds;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -873497067;

		/**
		 * Succeeds after a specified amount of time has passed. Can be called before initialization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetAlarm() {}

		/**
		 * Succeeds after a specified amount of time has passed. Can be called before initialization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param seconds Number of seconds before the function returns.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetAlarm(double seconds) {
			this.seconds = seconds;
		}

		/**
		 * Succeeds after a specified amount of time has passed. Can be called before initialization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetAlarm(DataInput input) throws IOException {
			this.seconds = input.readDouble();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetAlarm.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetAlarm.CONSTRUCTOR);
			output.writeDouble(this.seconds);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetAlarm setAlarm = (SetAlarm) o;
			if (this.seconds != setAlarm.seconds) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Double.hashCode(this.seconds);
		}
	}

	/**
	 * Sets the email address of the user and sends an authentication code
	 * to the email address. Works only when the current authorization state
	 * is authorizationStateWaitEmailAddress.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetAuthenticationEmailAddress extends Function<Ok> {


		/**
		 * The email address of the user.
		**/
		public String emailAddress;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1773323522;

		/**
		 * Sets the email address of the user and sends an authentication code to the email address. Works only when the current authorization state is authorizationStateWaitEmailAddress.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetAuthenticationEmailAddress() {}

		/**
		 * Sets the email address of the user and sends an authentication code to the email address. Works only when the current authorization state is authorizationStateWaitEmailAddress.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param emailAddress The email address of the user.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetAuthenticationEmailAddress(String emailAddress) {
			this.emailAddress = emailAddress;
		}

		/**
		 * Sets the email address of the user and sends an authentication code to the email address. Works only when the current authorization state is authorizationStateWaitEmailAddress.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetAuthenticationEmailAddress(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] emailAddressTmp = new byte[input.readInt()];
				input.readFully(emailAddressTmp);
				this.emailAddress = new String(emailAddressTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetAuthenticationEmailAddress.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetAuthenticationEmailAddress.CONSTRUCTOR);
			if (this.emailAddress == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] emailAddressTmp = this.emailAddress.getBytes(StandardCharsets.UTF_8);
				output.writeInt(emailAddressTmp.length);
				output.write(emailAddressTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetAuthenticationEmailAddress setAuthenticationEmailAddress = (SetAuthenticationEmailAddress) o;
			if (this.emailAddress != setAuthenticationEmailAddress.emailAddress) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.emailAddress == null ? 0 : this.emailAddress.hashCode();
		}
	}

	/**
	 * Sets the phone number of the user and sends an authentication code to
	 * the user. Works only when the current authorization state is
	 * authorizationStateWaitPhoneNumber, or if there is no pending
	 * authentication query and the current authorization state is
	 * authorizationStateWaitEmailAddress, authorizationStateWaitEmailCode,
	 * authorizationStateWaitCode, authorizationStateWaitRegistration, or
	 * authorizationStateWaitPassword.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetAuthenticationPhoneNumber extends Function<Ok> {


		/**
		 * The phone number of the user, in international format.
		**/
		public String phoneNumber;

		/**
		 * Settings for the authentication of the user&#039;s phone number; pass null to use default settings.
		**/
		public PhoneNumberAuthenticationSettings settings;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 868276259;

		/**
		 * Sets the phone number of the user and sends an authentication code to the user. Works only when the current authorization state is authorizationStateWaitPhoneNumber, or if there is no pending authentication query and the current authorization state is authorizationStateWaitEmailAddress, authorizationStateWaitEmailCode, authorizationStateWaitCode, authorizationStateWaitRegistration, or authorizationStateWaitPassword.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetAuthenticationPhoneNumber() {}

		/**
		 * Sets the phone number of the user and sends an authentication code to the user. Works only when the current authorization state is authorizationStateWaitPhoneNumber, or if there is no pending authentication query and the current authorization state is authorizationStateWaitEmailAddress, authorizationStateWaitEmailCode, authorizationStateWaitCode, authorizationStateWaitRegistration, or authorizationStateWaitPassword.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param phoneNumber The phone number of the user, in international format.
		 * @param settings Settings for the authentication of the user&#039;s phone number; pass null to use default settings.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetAuthenticationPhoneNumber(String phoneNumber,
				PhoneNumberAuthenticationSettings settings) {
			this.phoneNumber = phoneNumber;
			this.settings = settings;
		}

		/**
		 * Sets the phone number of the user and sends an authentication code to the user. Works only when the current authorization state is authorizationStateWaitPhoneNumber, or if there is no pending authentication query and the current authorization state is authorizationStateWaitEmailAddress, authorizationStateWaitEmailCode, authorizationStateWaitCode, authorizationStateWaitRegistration, or authorizationStateWaitPassword.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetAuthenticationPhoneNumber(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] phoneNumberTmp = new byte[input.readInt()];
				input.readFully(phoneNumberTmp);
				this.phoneNumber = new String(phoneNumberTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (PhoneNumberAuthenticationSettings.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.settings = new PhoneNumberAuthenticationSettings(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetAuthenticationPhoneNumber.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetAuthenticationPhoneNumber.CONSTRUCTOR);
			if (this.phoneNumber == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] phoneNumberTmp = this.phoneNumber.getBytes(StandardCharsets.UTF_8);
				output.writeInt(phoneNumberTmp.length);
				output.write(phoneNumberTmp);
			}
			if (this.settings == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.settings.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetAuthenticationPhoneNumber setAuthenticationPhoneNumber = (SetAuthenticationPhoneNumber) o;
			if (this.phoneNumber != setAuthenticationPhoneNumber.phoneNumber) {
				return false;
			}
			if (!Objects.equals(this.settings, setAuthenticationPhoneNumber.settings)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.phoneNumber == null ? 0 : this.phoneNumber.hashCode();
			result = result * 31 + (this.settings == null ? 0 : this.settings.hashCode());
			return result;
		}
	}

	/**
	 * Sets auto-download settings.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetAutoDownloadSettings extends Function<Ok> {


		/**
		 * New user auto-download settings.
		**/
		public AutoDownloadSettings settings;

		/**
		 * Type of the network for which the new settings are relevant.
		**/
		public NetworkType type;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -353671948;

		/**
		 * Sets auto-download settings.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetAutoDownloadSettings() {}

		/**
		 * Sets auto-download settings.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param settings New user auto-download settings.
		 * @param type Type of the network for which the new settings are relevant.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetAutoDownloadSettings(AutoDownloadSettings settings, NetworkType type) {
			this.settings = settings;
			this.type = type;
		}

		/**
		 * Sets auto-download settings.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetAutoDownloadSettings(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (AutoDownloadSettings.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.settings = new AutoDownloadSettings(input);
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case NetworkTypeNone.CONSTRUCTOR: this.type = new NetworkTypeNone(input); break;
					case NetworkTypeMobile.CONSTRUCTOR: this.type = new NetworkTypeMobile(input); break;
					case NetworkTypeMobileRoaming.CONSTRUCTOR: this.type = new NetworkTypeMobileRoaming(input); break;
					case NetworkTypeWiFi.CONSTRUCTOR: this.type = new NetworkTypeWiFi(input); break;
					case NetworkTypeOther.CONSTRUCTOR: this.type = new NetworkTypeOther(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetAutoDownloadSettings.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetAutoDownloadSettings.CONSTRUCTOR);
			if (this.settings == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.settings.serialize(output);
			}
			if (this.type == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.type.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetAutoDownloadSettings setAutoDownloadSettings = (SetAutoDownloadSettings) o;
			if (!Objects.equals(this.settings, setAutoDownloadSettings.settings)) {
				return false;
			}
			if (!Objects.equals(this.type, setAutoDownloadSettings.type)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.settings == null ? 0 : this.settings.hashCode();
			result = result * 31 + (this.type == null ? 0 : this.type.hashCode());
			return result;
		}
	}

	/**
	 * Sets autosave settings for the given scope. The method is guaranteed
	 * to work only after at least one call to getAutosaveSettings.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetAutosaveSettings extends Function<Ok> {


		/**
		 * Autosave settings scope.
		**/
		public AutosaveSettingsScope scope;

		/**
		 * New autosave settings for the scope; pass null to set autosave settings to default.
		**/
		public ScopeAutosaveSettings settings;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 6846656;

		/**
		 * Sets autosave settings for the given scope. The method is guaranteed to work only after at least one call to getAutosaveSettings.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetAutosaveSettings() {}

		/**
		 * Sets autosave settings for the given scope. The method is guaranteed to work only after at least one call to getAutosaveSettings.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param scope Autosave settings scope.
		 * @param settings New autosave settings for the scope; pass null to set autosave settings to default.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetAutosaveSettings(AutosaveSettingsScope scope, ScopeAutosaveSettings settings) {
			this.scope = scope;
			this.settings = settings;
		}

		/**
		 * Sets autosave settings for the given scope. The method is guaranteed to work only after at least one call to getAutosaveSettings.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetAutosaveSettings(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case AutosaveSettingsScopePrivateChats.CONSTRUCTOR: this.scope = new AutosaveSettingsScopePrivateChats(input); break;
					case AutosaveSettingsScopeGroupChats.CONSTRUCTOR: this.scope = new AutosaveSettingsScopeGroupChats(input); break;
					case AutosaveSettingsScopeChannelChats.CONSTRUCTOR: this.scope = new AutosaveSettingsScopeChannelChats(input); break;
					case AutosaveSettingsScopeChat.CONSTRUCTOR: this.scope = new AutosaveSettingsScopeChat(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				if (ScopeAutosaveSettings.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.settings = new ScopeAutosaveSettings(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetAutosaveSettings.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetAutosaveSettings.CONSTRUCTOR);
			if (this.scope == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.scope.serialize(output);
			}
			if (this.settings == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.settings.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetAutosaveSettings setAutosaveSettings = (SetAutosaveSettings) o;
			if (!Objects.equals(this.scope, setAutosaveSettings.scope)) {
				return false;
			}
			if (!Objects.equals(this.settings, setAutosaveSettings.settings)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.scope == null ? 0 : this.scope.hashCode();
			result = result * 31 + (this.settings == null ? 0 : this.settings.hashCode());
			return result;
		}
	}

	/**
	 * Changes the background selected by the user; adds background to the
	 * list of installed backgrounds.
	 * <p> Returns {@link Background Background} </p>
	**/
	public static final class SetBackground extends Function<Background> {


		/**
		 * The input background to use; pass null to create a new filled background or to remove the current background.
		**/
		public InputBackground background;

		/**
		 * Background type; pass null to use the default type of the remote background or to remove the current background.
		**/
		public BackgroundType type;

		/**
		 * Pass true if the background is changed for a dark theme.
		**/
		public boolean forDarkTheme;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1035439225;

		/**
		 * Changes the background selected by the user; adds background to the list of installed backgrounds.
		 *
		 * <p> Returns {@link Background Background} </p>
		**/
		public SetBackground() {}

		/**
		 * Changes the background selected by the user; adds background to the list of installed backgrounds.
		 *
		 * <p> Returns {@link Background Background} </p>
		 *
		 * @param background The input background to use; pass null to create a new filled background or to remove the current background.
		 * @param type Background type; pass null to use the default type of the remote background or to remove the current background.
		 * @param forDarkTheme Pass true if the background is changed for a dark theme.
		 *
		 * <p> Returns {@link Background Background} </p>
		**/
		public SetBackground(InputBackground background,
				BackgroundType type,
				boolean forDarkTheme) {
			this.background = background;
			this.type = type;
			this.forDarkTheme = forDarkTheme;
		}

		/**
		 * Changes the background selected by the user; adds background to the list of installed backgrounds.
		 *
		 * <p> Returns {@link Background Background} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetBackground(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputBackgroundLocal.CONSTRUCTOR: this.background = new InputBackgroundLocal(input); break;
					case InputBackgroundRemote.CONSTRUCTOR: this.background = new InputBackgroundRemote(input); break;
					case InputBackgroundPrevious.CONSTRUCTOR: this.background = new InputBackgroundPrevious(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case BackgroundTypeWallpaper.CONSTRUCTOR: this.type = new BackgroundTypeWallpaper(input); break;
					case BackgroundTypePattern.CONSTRUCTOR: this.type = new BackgroundTypePattern(input); break;
					case BackgroundTypeFill.CONSTRUCTOR: this.type = new BackgroundTypeFill(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.forDarkTheme = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetBackground.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetBackground.CONSTRUCTOR);
			if (this.background == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.background.serialize(output);
			}
			if (this.type == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.type.serialize(output);
			}
			output.writeBoolean(this.forDarkTheme);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetBackground setBackground = (SetBackground) o;
			if (!Objects.equals(this.background, setBackground.background)) {
				return false;
			}
			if (!Objects.equals(this.type, setBackground.type)) {
				return false;
			}
			if (this.forDarkTheme != setBackground.forDarkTheme) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.forDarkTheme);
			result = result * 31 + (this.background == null ? 0 : this.background.hashCode());
			result = result * 31 + (this.type == null ? 0 : this.type.hashCode());
			return result;
		}
	}

	/**
	 * Changes the bio of the current user.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetBio extends Function<Ok> {


		/**
		 * The new value of the user bio; 0-getOption(&quot;bio_length_max&quot;) characters without line feeds.
		**/
		public String bio;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1619582124;

		/**
		 * Changes the bio of the current user.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetBio() {}

		/**
		 * Changes the bio of the current user.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param bio The new value of the user bio; 0-getOption(&quot;bio_length_max&quot;) characters without line feeds.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetBio(String bio) {
			this.bio = bio;
		}

		/**
		 * Changes the bio of the current user.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetBio(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] bioTmp = new byte[input.readInt()];
				input.readFully(bioTmp);
				this.bio = new String(bioTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetBio.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetBio.CONSTRUCTOR);
			if (this.bio == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] bioTmp = this.bio.getBytes(StandardCharsets.UTF_8);
				output.writeInt(bioTmp.length);
				output.write(bioTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetBio setBio = (SetBio) o;
			if (this.bio != setBio.bio) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.bio == null ? 0 : this.bio.hashCode();
		}
	}

	/**
	 * Sets the text shown in the chat with a bot if the chat is empty. Can
	 * be called only if userTypeBot.canBeEdited == true.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetBotInfoDescription extends Function<Ok> {


		/**
		 * Identifier of the target bot.
		**/
		public long botUserId;

		/**
		 * A two-letter ISO 639-1 language code. If empty, the description will be shown to all users for whose languages there is no dedicated description.
		**/
		public String languageCode;

		/**
		 * New bot&#039;s description on the specified language.
		**/
		public String description;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 693574984;

		/**
		 * Sets the text shown in the chat with a bot if the chat is empty. Can be called only if userTypeBot.canBeEdited == true.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetBotInfoDescription() {}

		/**
		 * Sets the text shown in the chat with a bot if the chat is empty. Can be called only if userTypeBot.canBeEdited == true.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param botUserId Identifier of the target bot.
		 * @param languageCode A two-letter ISO 639-1 language code. If empty, the description will be shown to all users for whose languages there is no dedicated description.
		 * @param description New bot&#039;s description on the specified language.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetBotInfoDescription(long botUserId, String languageCode, String description) {
			this.botUserId = botUserId;
			this.languageCode = languageCode;
			this.description = description;
		}

		/**
		 * Sets the text shown in the chat with a bot if the chat is empty. Can be called only if userTypeBot.canBeEdited == true.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetBotInfoDescription(DataInput input) throws IOException {
			this.botUserId = input.readLong();
			if (input.readBoolean()) {
				byte[] languageCodeTmp = new byte[input.readInt()];
				input.readFully(languageCodeTmp);
				this.languageCode = new String(languageCodeTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] descriptionTmp = new byte[input.readInt()];
				input.readFully(descriptionTmp);
				this.description = new String(descriptionTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetBotInfoDescription.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetBotInfoDescription.CONSTRUCTOR);
			output.writeLong(this.botUserId);
			if (this.languageCode == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] languageCodeTmp = this.languageCode.getBytes(StandardCharsets.UTF_8);
				output.writeInt(languageCodeTmp.length);
				output.write(languageCodeTmp);
			}
			if (this.description == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] descriptionTmp = this.description.getBytes(StandardCharsets.UTF_8);
				output.writeInt(descriptionTmp.length);
				output.write(descriptionTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetBotInfoDescription setBotInfoDescription = (SetBotInfoDescription) o;
			if (this.botUserId != setBotInfoDescription.botUserId) {
				return false;
			}
			if (this.languageCode != setBotInfoDescription.languageCode) {
				return false;
			}
			if (this.description != setBotInfoDescription.description) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.botUserId);
			result = result * 31 + (this.languageCode == null ? 0 : this.languageCode.hashCode());
			result = result * 31 + (this.description == null ? 0 : this.description.hashCode());
			return result;
		}
	}

	/**
	 * Sets the text shown on a bot&#039;s profile page and sent together
	 * with the link when users share the bot. Can be called only if
	 * userTypeBot.canBeEdited == true.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetBotInfoShortDescription extends Function<Ok> {


		/**
		 * Identifier of the target bot.
		**/
		public long botUserId;

		/**
		 * A two-letter ISO 639-1 language code. If empty, the short description will be shown to all users for whose languages there is no dedicated description.
		**/
		public String languageCode;

		/**
		 * New bot&#039;s short description on the specified language.
		**/
		public String shortDescription;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 982956771;

		/**
		 * Sets the text shown on a bot&#039;s profile page and sent together with the link when users share the bot. Can be called only if userTypeBot.canBeEdited == true.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetBotInfoShortDescription() {}

		/**
		 * Sets the text shown on a bot&#039;s profile page and sent together with the link when users share the bot. Can be called only if userTypeBot.canBeEdited == true.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param botUserId Identifier of the target bot.
		 * @param languageCode A two-letter ISO 639-1 language code. If empty, the short description will be shown to all users for whose languages there is no dedicated description.
		 * @param shortDescription New bot&#039;s short description on the specified language.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetBotInfoShortDescription(long botUserId, String languageCode, String shortDescription) {
			this.botUserId = botUserId;
			this.languageCode = languageCode;
			this.shortDescription = shortDescription;
		}

		/**
		 * Sets the text shown on a bot&#039;s profile page and sent together with the link when users share the bot. Can be called only if userTypeBot.canBeEdited == true.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetBotInfoShortDescription(DataInput input) throws IOException {
			this.botUserId = input.readLong();
			if (input.readBoolean()) {
				byte[] languageCodeTmp = new byte[input.readInt()];
				input.readFully(languageCodeTmp);
				this.languageCode = new String(languageCodeTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] shortDescriptionTmp = new byte[input.readInt()];
				input.readFully(shortDescriptionTmp);
				this.shortDescription = new String(shortDescriptionTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetBotInfoShortDescription.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetBotInfoShortDescription.CONSTRUCTOR);
			output.writeLong(this.botUserId);
			if (this.languageCode == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] languageCodeTmp = this.languageCode.getBytes(StandardCharsets.UTF_8);
				output.writeInt(languageCodeTmp.length);
				output.write(languageCodeTmp);
			}
			if (this.shortDescription == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] shortDescriptionTmp = this.shortDescription.getBytes(StandardCharsets.UTF_8);
				output.writeInt(shortDescriptionTmp.length);
				output.write(shortDescriptionTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetBotInfoShortDescription setBotInfoShortDescription = (SetBotInfoShortDescription) o;
			if (this.botUserId != setBotInfoShortDescription.botUserId) {
				return false;
			}
			if (this.languageCode != setBotInfoShortDescription.languageCode) {
				return false;
			}
			if (this.shortDescription != setBotInfoShortDescription.shortDescription) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.botUserId);
			result = result * 31 + (this.languageCode == null ? 0 : this.languageCode.hashCode());
			result = result * 31 + (this.shortDescription == null ? 0 : this.shortDescription.hashCode());
			return result;
		}
	}

	/**
	 * Sets the name of a bot. Can be called only if userTypeBot.canBeEdited
	 * == true.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetBotName extends Function<Ok> {


		/**
		 * Identifier of the target bot.
		**/
		public long botUserId;

		/**
		 * A two-letter ISO 639-1 language code. If empty, the name will be shown to all users for whose languages there is no dedicated name.
		**/
		public String languageCode;

		/**
		 * New bot&#039;s name on the specified language; 0-64 characters; must be non-empty if language code is empty.
		**/
		public String name;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -761922959;

		/**
		 * Sets the name of a bot. Can be called only if userTypeBot.canBeEdited == true.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetBotName() {}

		/**
		 * Sets the name of a bot. Can be called only if userTypeBot.canBeEdited == true.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param botUserId Identifier of the target bot.
		 * @param languageCode A two-letter ISO 639-1 language code. If empty, the name will be shown to all users for whose languages there is no dedicated name.
		 * @param name New bot&#039;s name on the specified language; 0-64 characters; must be non-empty if language code is empty.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetBotName(long botUserId, String languageCode, String name) {
			this.botUserId = botUserId;
			this.languageCode = languageCode;
			this.name = name;
		}

		/**
		 * Sets the name of a bot. Can be called only if userTypeBot.canBeEdited == true.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetBotName(DataInput input) throws IOException {
			this.botUserId = input.readLong();
			if (input.readBoolean()) {
				byte[] languageCodeTmp = new byte[input.readInt()];
				input.readFully(languageCodeTmp);
				this.languageCode = new String(languageCodeTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] nameTmp = new byte[input.readInt()];
				input.readFully(nameTmp);
				this.name = new String(nameTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetBotName.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetBotName.CONSTRUCTOR);
			output.writeLong(this.botUserId);
			if (this.languageCode == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] languageCodeTmp = this.languageCode.getBytes(StandardCharsets.UTF_8);
				output.writeInt(languageCodeTmp.length);
				output.write(languageCodeTmp);
			}
			if (this.name == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nameTmp = this.name.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nameTmp.length);
				output.write(nameTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetBotName setBotName = (SetBotName) o;
			if (this.botUserId != setBotName.botUserId) {
				return false;
			}
			if (this.languageCode != setBotName.languageCode) {
				return false;
			}
			if (this.name != setBotName.name) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.botUserId);
			result = result * 31 + (this.languageCode == null ? 0 : this.languageCode.hashCode());
			result = result * 31 + (this.name == null ? 0 : this.name.hashCode());
			return result;
		}
	}

	/**
	 * Changes a profile photo for a bot.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetBotProfilePhoto extends Function<Ok> {


		/**
		 * Identifier of the target bot.
		**/
		public long botUserId;

		/**
		 * Profile photo to set; pass null to delete the chat photo.
		**/
		public InputChatPhoto photo;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1115272346;

		/**
		 * Changes a profile photo for a bot.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetBotProfilePhoto() {}

		/**
		 * Changes a profile photo for a bot.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param botUserId Identifier of the target bot.
		 * @param photo Profile photo to set; pass null to delete the chat photo.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetBotProfilePhoto(long botUserId, InputChatPhoto photo) {
			this.botUserId = botUserId;
			this.photo = photo;
		}

		/**
		 * Changes a profile photo for a bot.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetBotProfilePhoto(DataInput input) throws IOException {
			this.botUserId = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputChatPhotoPrevious.CONSTRUCTOR: this.photo = new InputChatPhotoPrevious(input); break;
					case InputChatPhotoStatic.CONSTRUCTOR: this.photo = new InputChatPhotoStatic(input); break;
					case InputChatPhotoAnimation.CONSTRUCTOR: this.photo = new InputChatPhotoAnimation(input); break;
					case InputChatPhotoSticker.CONSTRUCTOR: this.photo = new InputChatPhotoSticker(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetBotProfilePhoto.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetBotProfilePhoto.CONSTRUCTOR);
			output.writeLong(this.botUserId);
			if (this.photo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.photo.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetBotProfilePhoto setBotProfilePhoto = (SetBotProfilePhoto) o;
			if (this.botUserId != setBotProfilePhoto.botUserId) {
				return false;
			}
			if (!Objects.equals(this.photo, setBotProfilePhoto.photo)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.botUserId);
			result = result * 31 + (this.photo == null ? 0 : this.photo.hashCode());
			return result;
		}
	}

	/**
	 * Informs the server about the number of pending bot updates if they
	 * haven&#039;t been processed for a long time; for bots only.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetBotUpdatesStatus extends Function<Ok> {


		/**
		 * The number of pending updates.
		**/
		public int pendingUpdateCount;

		/**
		 * The last error message.
		**/
		public String errorMessage;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1154926191;

		/**
		 * Informs the server about the number of pending bot updates if they haven&#039;t been processed for a long time; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetBotUpdatesStatus() {}

		/**
		 * Informs the server about the number of pending bot updates if they haven&#039;t been processed for a long time; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param pendingUpdateCount The number of pending updates.
		 * @param errorMessage The last error message.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetBotUpdatesStatus(int pendingUpdateCount, String errorMessage) {
			this.pendingUpdateCount = pendingUpdateCount;
			this.errorMessage = errorMessage;
		}

		/**
		 * Informs the server about the number of pending bot updates if they haven&#039;t been processed for a long time; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetBotUpdatesStatus(DataInput input) throws IOException {
			this.pendingUpdateCount = input.readInt();
			if (input.readBoolean()) {
				byte[] errorMessageTmp = new byte[input.readInt()];
				input.readFully(errorMessageTmp);
				this.errorMessage = new String(errorMessageTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetBotUpdatesStatus.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetBotUpdatesStatus.CONSTRUCTOR);
			output.writeInt(this.pendingUpdateCount);
			if (this.errorMessage == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] errorMessageTmp = this.errorMessage.getBytes(StandardCharsets.UTF_8);
				output.writeInt(errorMessageTmp.length);
				output.write(errorMessageTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetBotUpdatesStatus setBotUpdatesStatus = (SetBotUpdatesStatus) o;
			if (this.pendingUpdateCount != setBotUpdatesStatus.pendingUpdateCount) {
				return false;
			}
			if (this.errorMessage != setBotUpdatesStatus.errorMessage) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.pendingUpdateCount);
			result = result * 31 + (this.errorMessage == null ? 0 : this.errorMessage.hashCode());
			return result;
		}
	}

	/**
	 * Changes reactions, available in a chat. Available for basic groups,
	 * supergroups, and channels. Requires canChangeInfo administrator
	 * right.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetChatAvailableReactions extends Function<Ok> {


		/**
		 * Identifier of the chat.
		**/
		public long chatId;

		/**
		 * Reactions available in the chat. All emoji reactions must be active.
		**/
		public ChatAvailableReactions availableReactions;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 267075078;

		/**
		 * Changes reactions, available in a chat. Available for basic groups, supergroups, and channels. Requires canChangeInfo administrator right.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetChatAvailableReactions() {}

		/**
		 * Changes reactions, available in a chat. Available for basic groups, supergroups, and channels. Requires canChangeInfo administrator right.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Identifier of the chat.
		 * @param availableReactions Reactions available in the chat. All emoji reactions must be active.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetChatAvailableReactions(long chatId, ChatAvailableReactions availableReactions) {
			this.chatId = chatId;
			this.availableReactions = availableReactions;
		}

		/**
		 * Changes reactions, available in a chat. Available for basic groups, supergroups, and channels. Requires canChangeInfo administrator right.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetChatAvailableReactions(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ChatAvailableReactionsAll.CONSTRUCTOR: this.availableReactions = new ChatAvailableReactionsAll(input); break;
					case ChatAvailableReactionsSome.CONSTRUCTOR: this.availableReactions = new ChatAvailableReactionsSome(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetChatAvailableReactions.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetChatAvailableReactions.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.availableReactions == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.availableReactions.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetChatAvailableReactions setChatAvailableReactions = (SetChatAvailableReactions) o;
			if (this.chatId != setChatAvailableReactions.chatId) {
				return false;
			}
			if (!Objects.equals(this.availableReactions, setChatAvailableReactions.availableReactions)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.availableReactions == null ? 0 : this.availableReactions.hashCode());
			return result;
		}
	}

	/**
	 * Changes the background in a specific chat. Supported only in private
	 * and secret chats with non-deleted users.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetChatBackground extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * The input background to use; pass null to create a new filled background or to remove the current background.
		**/
		public InputBackground background;

		/**
		 * Background type; pass null to remove the current background.
		**/
		public BackgroundType type;

		/**
		 * Dimming of the background in dark themes, as a percentage; 0-100.
		**/
		public int darkThemeDimming;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1027545896;

		/**
		 * Changes the background in a specific chat. Supported only in private and secret chats with non-deleted users.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetChatBackground() {}

		/**
		 * Changes the background in a specific chat. Supported only in private and secret chats with non-deleted users.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param background The input background to use; pass null to create a new filled background or to remove the current background.
		 * @param type Background type; pass null to remove the current background.
		 * @param darkThemeDimming Dimming of the background in dark themes, as a percentage; 0-100.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetChatBackground(long chatId,
				InputBackground background,
				BackgroundType type,
				int darkThemeDimming) {
			this.chatId = chatId;
			this.background = background;
			this.type = type;
			this.darkThemeDimming = darkThemeDimming;
		}

		/**
		 * Changes the background in a specific chat. Supported only in private and secret chats with non-deleted users.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetChatBackground(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputBackgroundLocal.CONSTRUCTOR: this.background = new InputBackgroundLocal(input); break;
					case InputBackgroundRemote.CONSTRUCTOR: this.background = new InputBackgroundRemote(input); break;
					case InputBackgroundPrevious.CONSTRUCTOR: this.background = new InputBackgroundPrevious(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case BackgroundTypeWallpaper.CONSTRUCTOR: this.type = new BackgroundTypeWallpaper(input); break;
					case BackgroundTypePattern.CONSTRUCTOR: this.type = new BackgroundTypePattern(input); break;
					case BackgroundTypeFill.CONSTRUCTOR: this.type = new BackgroundTypeFill(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.darkThemeDimming = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetChatBackground.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetChatBackground.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.background == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.background.serialize(output);
			}
			if (this.type == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.type.serialize(output);
			}
			output.writeInt(this.darkThemeDimming);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetChatBackground setChatBackground = (SetChatBackground) o;
			if (this.chatId != setChatBackground.chatId) {
				return false;
			}
			if (!Objects.equals(this.background, setChatBackground.background)) {
				return false;
			}
			if (!Objects.equals(this.type, setChatBackground.type)) {
				return false;
			}
			if (this.darkThemeDimming != setChatBackground.darkThemeDimming) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.background == null ? 0 : this.background.hashCode());
			result = result * 31 + (this.type == null ? 0 : this.type.hashCode());
			return result;
		}
	}

	/**
	 * Changes application-specific data associated with a chat.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetChatClientData extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * New value of clientData.
		**/
		public String clientData;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -827119811;

		/**
		 * Changes application-specific data associated with a chat.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetChatClientData() {}

		/**
		 * Changes application-specific data associated with a chat.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param clientData New value of clientData.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetChatClientData(long chatId, String clientData) {
			this.chatId = chatId;
			this.clientData = clientData;
		}

		/**
		 * Changes application-specific data associated with a chat.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetChatClientData(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				byte[] clientDataTmp = new byte[input.readInt()];
				input.readFully(clientDataTmp);
				this.clientData = new String(clientDataTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetChatClientData.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetChatClientData.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.clientData == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] clientDataTmp = this.clientData.getBytes(StandardCharsets.UTF_8);
				output.writeInt(clientDataTmp.length);
				output.write(clientDataTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetChatClientData setChatClientData = (SetChatClientData) o;
			if (this.chatId != setChatClientData.chatId) {
				return false;
			}
			if (this.clientData != setChatClientData.clientData) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.clientData == null ? 0 : this.clientData.hashCode());
			return result;
		}
	}

	/**
	 * Changes information about a chat. Available for basic groups,
	 * supergroups, and channels. Requires canChangeInfo administrator
	 * right.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetChatDescription extends Function<Ok> {


		/**
		 * Identifier of the chat.
		**/
		public long chatId;

		/**
		 * New chat description; 0-255 characters.
		**/
		public String description;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1957213277;

		/**
		 * Changes information about a chat. Available for basic groups, supergroups, and channels. Requires canChangeInfo administrator right.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetChatDescription() {}

		/**
		 * Changes information about a chat. Available for basic groups, supergroups, and channels. Requires canChangeInfo administrator right.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Identifier of the chat.
		 * @param description New chat description; 0-255 characters.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetChatDescription(long chatId, String description) {
			this.chatId = chatId;
			this.description = description;
		}

		/**
		 * Changes information about a chat. Available for basic groups, supergroups, and channels. Requires canChangeInfo administrator right.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetChatDescription(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				byte[] descriptionTmp = new byte[input.readInt()];
				input.readFully(descriptionTmp);
				this.description = new String(descriptionTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetChatDescription.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetChatDescription.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.description == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] descriptionTmp = this.description.getBytes(StandardCharsets.UTF_8);
				output.writeInt(descriptionTmp.length);
				output.write(descriptionTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetChatDescription setChatDescription = (SetChatDescription) o;
			if (this.chatId != setChatDescription.chatId) {
				return false;
			}
			if (this.description != setChatDescription.description) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.description == null ? 0 : this.description.hashCode());
			return result;
		}
	}

	/**
	 * Changes the discussion group of a channel chat; requires
	 * canChangeInfo administrator right in the channel if it is specified.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetChatDiscussionGroup extends Function<Ok> {


		/**
		 * Identifier of the channel chat. Pass 0 to remove a link from the supergroup passed in the second argument to a linked channel chat (requires canPinMessages rights in the supergroup).
		**/
		public long chatId;

		/**
		 * Identifier of a new channel&#039;s discussion group. Use 0 to remove the discussion group. Use the method getSuitableDiscussionChats to find all suitable groups. Basic group chats must be first upgraded to supergroup chats. If new chat members don&#039;t have access to old messages in the supergroup, then toggleSupergroupIsAllHistoryAvailable must be used first to change that.
		**/
		public long discussionChatId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -918801736;

		/**
		 * Changes the discussion group of a channel chat; requires canChangeInfo administrator right in the channel if it is specified.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetChatDiscussionGroup() {}

		/**
		 * Changes the discussion group of a channel chat; requires canChangeInfo administrator right in the channel if it is specified.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Identifier of the channel chat. Pass 0 to remove a link from the supergroup passed in the second argument to a linked channel chat (requires canPinMessages rights in the supergroup).
		 * @param discussionChatId Identifier of a new channel&#039;s discussion group. Use 0 to remove the discussion group. Use the method getSuitableDiscussionChats to find all suitable groups. Basic group chats must be first upgraded to supergroup chats. If new chat members don&#039;t have access to old messages in the supergroup, then toggleSupergroupIsAllHistoryAvailable must be used first to change that.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetChatDiscussionGroup(long chatId, long discussionChatId) {
			this.chatId = chatId;
			this.discussionChatId = discussionChatId;
		}

		/**
		 * Changes the discussion group of a channel chat; requires canChangeInfo administrator right in the channel if it is specified.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetChatDiscussionGroup(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.discussionChatId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetChatDiscussionGroup.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetChatDiscussionGroup.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.discussionChatId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetChatDiscussionGroup setChatDiscussionGroup = (SetChatDiscussionGroup) o;
			if (this.chatId != setChatDiscussionGroup.chatId) {
				return false;
			}
			if (this.discussionChatId != setChatDiscussionGroup.discussionChatId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Changes the draft message in a chat.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetChatDraftMessage extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * If not 0, a message thread identifier in which the draft was changed.
		**/
		public long messageThreadId;

		/**
		 * New draft message; pass null to remove the draft.
		**/
		public DraftMessage draftMessage;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1683889946;

		/**
		 * Changes the draft message in a chat.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetChatDraftMessage() {}

		/**
		 * Changes the draft message in a chat.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param messageThreadId If not 0, a message thread identifier in which the draft was changed.
		 * @param draftMessage New draft message; pass null to remove the draft.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetChatDraftMessage(long chatId, long messageThreadId, DraftMessage draftMessage) {
			this.chatId = chatId;
			this.messageThreadId = messageThreadId;
			this.draftMessage = draftMessage;
		}

		/**
		 * Changes the draft message in a chat.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetChatDraftMessage(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageThreadId = input.readLong();
			if (input.readBoolean()) {
				if (DraftMessage.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.draftMessage = new DraftMessage(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetChatDraftMessage.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetChatDraftMessage.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageThreadId);
			if (this.draftMessage == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.draftMessage.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetChatDraftMessage setChatDraftMessage = (SetChatDraftMessage) o;
			if (this.chatId != setChatDraftMessage.chatId) {
				return false;
			}
			if (this.messageThreadId != setChatDraftMessage.messageThreadId) {
				return false;
			}
			if (!Objects.equals(this.draftMessage, setChatDraftMessage.draftMessage)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.draftMessage == null ? 0 : this.draftMessage.hashCode());
			return result;
		}
	}

	/**
	 * Changes the location of a chat. Available only for some
	 * location-based supergroups, use supergroupFullInfo.canSetLocation to
	 * check whether the method is allowed to use.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetChatLocation extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * New location for the chat; must be valid and not null.
		**/
		public ChatLocation location;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -767091286;

		/**
		 * Changes the location of a chat. Available only for some location-based supergroups, use supergroupFullInfo.canSetLocation to check whether the method is allowed to use.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetChatLocation() {}

		/**
		 * Changes the location of a chat. Available only for some location-based supergroups, use supergroupFullInfo.canSetLocation to check whether the method is allowed to use.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param location New location for the chat; must be valid and not null.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetChatLocation(long chatId, ChatLocation location) {
			this.chatId = chatId;
			this.location = location;
		}

		/**
		 * Changes the location of a chat. Available only for some location-based supergroups, use supergroupFullInfo.canSetLocation to check whether the method is allowed to use.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetChatLocation(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				if (ChatLocation.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.location = new ChatLocation(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetChatLocation.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetChatLocation.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.location == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.location.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetChatLocation setChatLocation = (SetChatLocation) o;
			if (this.chatId != setChatLocation.chatId) {
				return false;
			}
			if (!Objects.equals(this.location, setChatLocation.location)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.location == null ? 0 : this.location.hashCode());
			return result;
		}
	}

	/**
	 * Changes the status of a chat member, needs appropriate privileges.
	 * This function is currently not suitable for transferring chat
	 * ownership; use transferChatOwnership instead. Use addChatMember or
	 * banChatMember if some additional parameters needs to be passed.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetChatMemberStatus extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Member identifier. Chats can be only banned and unbanned in supergroups and channels.
		**/
		public MessageSender memberId;

		/**
		 * The new status of the member in the chat.
		**/
		public ChatMemberStatus status;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 81794847;

		/**
		 * Changes the status of a chat member, needs appropriate privileges. This function is currently not suitable for transferring chat ownership; use transferChatOwnership instead. Use addChatMember or banChatMember if some additional parameters needs to be passed.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetChatMemberStatus() {}

		/**
		 * Changes the status of a chat member, needs appropriate privileges. This function is currently not suitable for transferring chat ownership; use transferChatOwnership instead. Use addChatMember or banChatMember if some additional parameters needs to be passed.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param memberId Member identifier. Chats can be only banned and unbanned in supergroups and channels.
		 * @param status The new status of the member in the chat.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetChatMemberStatus(long chatId, MessageSender memberId, ChatMemberStatus status) {
			this.chatId = chatId;
			this.memberId = memberId;
			this.status = status;
		}

		/**
		 * Changes the status of a chat member, needs appropriate privileges. This function is currently not suitable for transferring chat ownership; use transferChatOwnership instead. Use addChatMember or banChatMember if some additional parameters needs to be passed.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetChatMemberStatus(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case MessageSenderUser.CONSTRUCTOR: this.memberId = new MessageSenderUser(input); break;
					case MessageSenderChat.CONSTRUCTOR: this.memberId = new MessageSenderChat(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ChatMemberStatusCreator.CONSTRUCTOR: this.status = new ChatMemberStatusCreator(input); break;
					case ChatMemberStatusAdministrator.CONSTRUCTOR: this.status = new ChatMemberStatusAdministrator(input); break;
					case ChatMemberStatusMember.CONSTRUCTOR: this.status = new ChatMemberStatusMember(input); break;
					case ChatMemberStatusRestricted.CONSTRUCTOR: this.status = new ChatMemberStatusRestricted(input); break;
					case ChatMemberStatusLeft.CONSTRUCTOR: this.status = new ChatMemberStatusLeft(input); break;
					case ChatMemberStatusBanned.CONSTRUCTOR: this.status = new ChatMemberStatusBanned(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetChatMemberStatus.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetChatMemberStatus.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.memberId == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.memberId.serialize(output);
			}
			if (this.status == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.status.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetChatMemberStatus setChatMemberStatus = (SetChatMemberStatus) o;
			if (this.chatId != setChatMemberStatus.chatId) {
				return false;
			}
			if (!Objects.equals(this.memberId, setChatMemberStatus.memberId)) {
				return false;
			}
			if (!Objects.equals(this.status, setChatMemberStatus.status)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.memberId == null ? 0 : this.memberId.hashCode());
			result = result * 31 + (this.status == null ? 0 : this.status.hashCode());
			return result;
		}
	}

	/**
	 * Changes the message auto-delete or self-destruct (for secret chats)
	 * time in a chat. Requires changeInfo administrator right in basic
	 * groups, supergroups and channels Message auto-delete time can&#039;t
	 * be changed in a chat with the current user (Saved Messages) and the
	 * chat 777000 (Telegram).
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetChatMessageAutoDeleteTime extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * New time value, in seconds; unless the chat is secret, it must be from 0 up to 365 * 86400 and be divisible by 86400. If 0, then messages aren&#039;t deleted automatically.
		**/
		public int messageAutoDeleteTime;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1505643265;

		/**
		 * Changes the message auto-delete or self-destruct (for secret chats) time in a chat. Requires changeInfo administrator right in basic groups, supergroups and channels Message auto-delete time can&#039;t be changed in a chat with the current user (Saved Messages) and the chat 777000 (Telegram).
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetChatMessageAutoDeleteTime() {}

		/**
		 * Changes the message auto-delete or self-destruct (for secret chats) time in a chat. Requires changeInfo administrator right in basic groups, supergroups and channels Message auto-delete time can&#039;t be changed in a chat with the current user (Saved Messages) and the chat 777000 (Telegram).
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param messageAutoDeleteTime New time value, in seconds; unless the chat is secret, it must be from 0 up to 365 * 86400 and be divisible by 86400. If 0, then messages aren&#039;t deleted automatically.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetChatMessageAutoDeleteTime(long chatId, int messageAutoDeleteTime) {
			this.chatId = chatId;
			this.messageAutoDeleteTime = messageAutoDeleteTime;
		}

		/**
		 * Changes the message auto-delete or self-destruct (for secret chats) time in a chat. Requires changeInfo administrator right in basic groups, supergroups and channels Message auto-delete time can&#039;t be changed in a chat with the current user (Saved Messages) and the chat 777000 (Telegram).
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetChatMessageAutoDeleteTime(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageAutoDeleteTime = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetChatMessageAutoDeleteTime.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetChatMessageAutoDeleteTime.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeInt(this.messageAutoDeleteTime);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetChatMessageAutoDeleteTime setChatMessageAutoDeleteTime = (SetChatMessageAutoDeleteTime) o;
			if (this.chatId != setChatMessageAutoDeleteTime.chatId) {
				return false;
			}
			if (this.messageAutoDeleteTime != setChatMessageAutoDeleteTime.messageAutoDeleteTime) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Selects a message sender to send messages in a chat.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetChatMessageSender extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * New message sender for the chat.
		**/
		public MessageSender messageSenderId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1421513858;

		/**
		 * Selects a message sender to send messages in a chat.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetChatMessageSender() {}

		/**
		 * Selects a message sender to send messages in a chat.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param messageSenderId New message sender for the chat.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetChatMessageSender(long chatId, MessageSender messageSenderId) {
			this.chatId = chatId;
			this.messageSenderId = messageSenderId;
		}

		/**
		 * Selects a message sender to send messages in a chat.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetChatMessageSender(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case MessageSenderUser.CONSTRUCTOR: this.messageSenderId = new MessageSenderUser(input); break;
					case MessageSenderChat.CONSTRUCTOR: this.messageSenderId = new MessageSenderChat(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetChatMessageSender.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetChatMessageSender.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.messageSenderId == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.messageSenderId.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetChatMessageSender setChatMessageSender = (SetChatMessageSender) o;
			if (this.chatId != setChatMessageSender.chatId) {
				return false;
			}
			if (!Objects.equals(this.messageSenderId, setChatMessageSender.messageSenderId)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.messageSenderId == null ? 0 : this.messageSenderId.hashCode());
			return result;
		}
	}

	/**
	 * Changes the notification settings of a chat. Notification settings of
	 * a chat with the current user (Saved Messages) can&#039;t be changed.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetChatNotificationSettings extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * New notification settings for the chat. If the chat is muted for more than 366 days, it is considered to be muted forever.
		**/
		public ChatNotificationSettings notificationSettings;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 777199614;

		/**
		 * Changes the notification settings of a chat. Notification settings of a chat with the current user (Saved Messages) can&#039;t be changed.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetChatNotificationSettings() {}

		/**
		 * Changes the notification settings of a chat. Notification settings of a chat with the current user (Saved Messages) can&#039;t be changed.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param notificationSettings New notification settings for the chat. If the chat is muted for more than 366 days, it is considered to be muted forever.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetChatNotificationSettings(long chatId, ChatNotificationSettings notificationSettings) {
			this.chatId = chatId;
			this.notificationSettings = notificationSettings;
		}

		/**
		 * Changes the notification settings of a chat. Notification settings of a chat with the current user (Saved Messages) can&#039;t be changed.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetChatNotificationSettings(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				if (ChatNotificationSettings.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.notificationSettings = new ChatNotificationSettings(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetChatNotificationSettings.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetChatNotificationSettings.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.notificationSettings == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.notificationSettings.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetChatNotificationSettings setChatNotificationSettings = (SetChatNotificationSettings) o;
			if (this.chatId != setChatNotificationSettings.chatId) {
				return false;
			}
			if (!Objects.equals(this.notificationSettings, setChatNotificationSettings.notificationSettings)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.notificationSettings == null ? 0 : this.notificationSettings.hashCode());
			return result;
		}
	}

	/**
	 * Changes the chat members permissions. Supported only for basic groups
	 * and supergroups. Requires canRestrictMembers administrator right.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetChatPermissions extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * New non-administrator members permissions in the chat.
		**/
		public ChatPermissions permissions;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2138507006;

		/**
		 * Changes the chat members permissions. Supported only for basic groups and supergroups. Requires canRestrictMembers administrator right.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetChatPermissions() {}

		/**
		 * Changes the chat members permissions. Supported only for basic groups and supergroups. Requires canRestrictMembers administrator right.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param permissions New non-administrator members permissions in the chat.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetChatPermissions(long chatId, ChatPermissions permissions) {
			this.chatId = chatId;
			this.permissions = permissions;
		}

		/**
		 * Changes the chat members permissions. Supported only for basic groups and supergroups. Requires canRestrictMembers administrator right.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetChatPermissions(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				if (ChatPermissions.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.permissions = new ChatPermissions(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetChatPermissions.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetChatPermissions.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.permissions == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.permissions.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetChatPermissions setChatPermissions = (SetChatPermissions) o;
			if (this.chatId != setChatPermissions.chatId) {
				return false;
			}
			if (!Objects.equals(this.permissions, setChatPermissions.permissions)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.permissions == null ? 0 : this.permissions.hashCode());
			return result;
		}
	}

	/**
	 * Changes the photo of a chat. Supported only for basic groups,
	 * supergroups and channels. Requires canChangeInfo administrator right.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetChatPhoto extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * New chat photo; pass null to delete the chat photo.
		**/
		public InputChatPhoto photo;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -377778941;

		/**
		 * Changes the photo of a chat. Supported only for basic groups, supergroups and channels. Requires canChangeInfo administrator right.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetChatPhoto() {}

		/**
		 * Changes the photo of a chat. Supported only for basic groups, supergroups and channels. Requires canChangeInfo administrator right.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param photo New chat photo; pass null to delete the chat photo.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetChatPhoto(long chatId, InputChatPhoto photo) {
			this.chatId = chatId;
			this.photo = photo;
		}

		/**
		 * Changes the photo of a chat. Supported only for basic groups, supergroups and channels. Requires canChangeInfo administrator right.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetChatPhoto(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputChatPhotoPrevious.CONSTRUCTOR: this.photo = new InputChatPhotoPrevious(input); break;
					case InputChatPhotoStatic.CONSTRUCTOR: this.photo = new InputChatPhotoStatic(input); break;
					case InputChatPhotoAnimation.CONSTRUCTOR: this.photo = new InputChatPhotoAnimation(input); break;
					case InputChatPhotoSticker.CONSTRUCTOR: this.photo = new InputChatPhotoSticker(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetChatPhoto.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetChatPhoto.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.photo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.photo.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetChatPhoto setChatPhoto = (SetChatPhoto) o;
			if (this.chatId != setChatPhoto.chatId) {
				return false;
			}
			if (!Objects.equals(this.photo, setChatPhoto.photo)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.photo == null ? 0 : this.photo.hashCode());
			return result;
		}
	}

	/**
	 * Changes the slow mode delay of a chat. Available only for
	 * supergroups; requires canRestrictMembers rights.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetChatSlowModeDelay extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * New slow mode delay for the chat, in seconds; must be one of 0, 10, 30, 60, 300, 900, 3600.
		**/
		public int slowModeDelay;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -540350914;

		/**
		 * Changes the slow mode delay of a chat. Available only for supergroups; requires canRestrictMembers rights.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetChatSlowModeDelay() {}

		/**
		 * Changes the slow mode delay of a chat. Available only for supergroups; requires canRestrictMembers rights.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param slowModeDelay New slow mode delay for the chat, in seconds; must be one of 0, 10, 30, 60, 300, 900, 3600.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetChatSlowModeDelay(long chatId, int slowModeDelay) {
			this.chatId = chatId;
			this.slowModeDelay = slowModeDelay;
		}

		/**
		 * Changes the slow mode delay of a chat. Available only for supergroups; requires canRestrictMembers rights.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetChatSlowModeDelay(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.slowModeDelay = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetChatSlowModeDelay.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetChatSlowModeDelay.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeInt(this.slowModeDelay);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetChatSlowModeDelay setChatSlowModeDelay = (SetChatSlowModeDelay) o;
			if (this.chatId != setChatSlowModeDelay.chatId) {
				return false;
			}
			if (this.slowModeDelay != setChatSlowModeDelay.slowModeDelay) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Changes the chat theme. Supported only in private and secret chats.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetChatTheme extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Name of the new chat theme; pass an empty string to return the default theme.
		**/
		public String themeName;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1895234925;

		/**
		 * Changes the chat theme. Supported only in private and secret chats.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetChatTheme() {}

		/**
		 * Changes the chat theme. Supported only in private and secret chats.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param themeName Name of the new chat theme; pass an empty string to return the default theme.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetChatTheme(long chatId, String themeName) {
			this.chatId = chatId;
			this.themeName = themeName;
		}

		/**
		 * Changes the chat theme. Supported only in private and secret chats.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetChatTheme(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				byte[] themeNameTmp = new byte[input.readInt()];
				input.readFully(themeNameTmp);
				this.themeName = new String(themeNameTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetChatTheme.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetChatTheme.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.themeName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] themeNameTmp = this.themeName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(themeNameTmp.length);
				output.write(themeNameTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetChatTheme setChatTheme = (SetChatTheme) o;
			if (this.chatId != setChatTheme.chatId) {
				return false;
			}
			if (this.themeName != setChatTheme.themeName) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.themeName == null ? 0 : this.themeName.hashCode());
			return result;
		}
	}

	/**
	 * Changes the chat title. Supported only for basic groups, supergroups
	 * and channels. Requires canChangeInfo administrator right.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetChatTitle extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * New title of the chat; 1-128 characters.
		**/
		public String title;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 164282047;

		/**
		 * Changes the chat title. Supported only for basic groups, supergroups and channels. Requires canChangeInfo administrator right.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetChatTitle() {}

		/**
		 * Changes the chat title. Supported only for basic groups, supergroups and channels. Requires canChangeInfo administrator right.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param title New title of the chat; 1-128 characters.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetChatTitle(long chatId, String title) {
			this.chatId = chatId;
			this.title = title;
		}

		/**
		 * Changes the chat title. Supported only for basic groups, supergroups and channels. Requires canChangeInfo administrator right.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetChatTitle(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetChatTitle.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetChatTitle.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetChatTitle setChatTitle = (SetChatTitle) o;
			if (this.chatId != setChatTitle.chatId) {
				return false;
			}
			if (this.title != setChatTitle.title) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.title == null ? 0 : this.title.hashCode());
			return result;
		}
	}

	/**
	 * Sets the list of commands supported by the bot for the given user
	 * scope and language; for bots only.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetCommands extends Function<Ok> {


		/**
		 * The scope to which the commands are relevant; pass null to change commands in the default bot command scope.
		**/
		public BotCommandScope scope;

		/**
		 * A two-letter ISO 639-1 language code. If empty, the commands will be applied to all users from the given scope, for which language there are no dedicated commands.
		**/
		public String languageCode;

		/**
		 * List of the bot&#039;s commands.
		**/
		public BotCommand[] commands;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -907165606;

		/**
		 * Sets the list of commands supported by the bot for the given user scope and language; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetCommands() {}

		/**
		 * Sets the list of commands supported by the bot for the given user scope and language; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param scope The scope to which the commands are relevant; pass null to change commands in the default bot command scope.
		 * @param languageCode A two-letter ISO 639-1 language code. If empty, the commands will be applied to all users from the given scope, for which language there are no dedicated commands.
		 * @param commands List of the bot&#039;s commands.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetCommands(BotCommandScope scope,
				String languageCode,
				BotCommand[] commands) {
			this.scope = scope;
			this.languageCode = languageCode;
			this.commands = commands;
		}

		/**
		 * Sets the list of commands supported by the bot for the given user scope and language; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetCommands(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case BotCommandScopeDefault.CONSTRUCTOR: this.scope = new BotCommandScopeDefault(input); break;
					case BotCommandScopeAllPrivateChats.CONSTRUCTOR: this.scope = new BotCommandScopeAllPrivateChats(input); break;
					case BotCommandScopeAllGroupChats.CONSTRUCTOR: this.scope = new BotCommandScopeAllGroupChats(input); break;
					case BotCommandScopeAllChatAdministrators.CONSTRUCTOR: this.scope = new BotCommandScopeAllChatAdministrators(input); break;
					case BotCommandScopeChat.CONSTRUCTOR: this.scope = new BotCommandScopeChat(input); break;
					case BotCommandScopeChatAdministrators.CONSTRUCTOR: this.scope = new BotCommandScopeChatAdministrators(input); break;
					case BotCommandScopeChatMember.CONSTRUCTOR: this.scope = new BotCommandScopeChatMember(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				byte[] languageCodeTmp = new byte[input.readInt()];
				input.readFully(languageCodeTmp);
				this.languageCode = new String(languageCodeTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				this.commands = new BotCommand[input.readInt()];
				for (int i = 0; i < this.commands.length; i++) {
					if (BotCommand.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.commands[i] = new BotCommand(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetCommands.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetCommands.CONSTRUCTOR);
			if (this.scope == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.scope.serialize(output);
			}
			if (this.languageCode == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] languageCodeTmp = this.languageCode.getBytes(StandardCharsets.UTF_8);
				output.writeInt(languageCodeTmp.length);
				output.write(languageCodeTmp);
			}
			if (this.commands == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.commands.length);
				for (int i = 0; i < this.commands.length; i++) {
					this.commands[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetCommands setCommands = (SetCommands) o;
			if (!Objects.equals(this.scope, setCommands.scope)) {
				return false;
			}
			if (this.languageCode != setCommands.languageCode) {
				return false;
			}
			if (!Arrays.equals(this.commands, setCommands.commands)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.scope == null ? 0 : this.scope.hashCode();
			result = result * 31 + (this.languageCode == null ? 0 : this.languageCode.hashCode());
			result = result * 31 + (Arrays.hashCode(this.commands));
			return result;
		}
	}

	/**
	 * Sets a custom emoji sticker set thumbnail; for bots only.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetCustomEmojiStickerSetThumbnail extends Function<Ok> {


		/**
		 * Sticker set name.
		**/
		public String name;

		/**
		 * Identifier of the custom emoji from the sticker set, which will be set as sticker set thumbnail; pass 0 to remove the sticker set thumbnail.
		**/
		public long customEmojiId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1122836246;

		/**
		 * Sets a custom emoji sticker set thumbnail; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetCustomEmojiStickerSetThumbnail() {}

		/**
		 * Sets a custom emoji sticker set thumbnail; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param name Sticker set name.
		 * @param customEmojiId Identifier of the custom emoji from the sticker set, which will be set as sticker set thumbnail; pass 0 to remove the sticker set thumbnail.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetCustomEmojiStickerSetThumbnail(String name, long customEmojiId) {
			this.name = name;
			this.customEmojiId = customEmojiId;
		}

		/**
		 * Sets a custom emoji sticker set thumbnail; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetCustomEmojiStickerSetThumbnail(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] nameTmp = new byte[input.readInt()];
				input.readFully(nameTmp);
				this.name = new String(nameTmp, StandardCharsets.UTF_8);
			}
			this.customEmojiId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetCustomEmojiStickerSetThumbnail.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetCustomEmojiStickerSetThumbnail.CONSTRUCTOR);
			if (this.name == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nameTmp = this.name.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nameTmp.length);
				output.write(nameTmp);
			}
			output.writeLong(this.customEmojiId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetCustomEmojiStickerSetThumbnail setCustomEmojiStickerSetThumbnail = (SetCustomEmojiStickerSetThumbnail) o;
			if (this.name != setCustomEmojiStickerSetThumbnail.name) {
				return false;
			}
			if (this.customEmojiId != setCustomEmojiStickerSetThumbnail.customEmojiId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.customEmojiId);
			result = result * 31 + (this.name == null ? 0 : this.name.hashCode());
			return result;
		}
	}

	/**
	 * Adds or changes a custom local language pack to the current
	 * localization target.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetCustomLanguagePack extends Function<Ok> {


		/**
		 * Information about the language pack. Language pack ID must start with &#039;X&#039;, consist only of English letters, digits and hyphens, and must not exceed 64 characters. Can be called before authorization.
		**/
		public LanguagePackInfo info;

		/**
		 * Strings of the new language pack.
		**/
		public LanguagePackString[] strings;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -296742819;

		/**
		 * Adds or changes a custom local language pack to the current localization target.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetCustomLanguagePack() {}

		/**
		 * Adds or changes a custom local language pack to the current localization target.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param info Information about the language pack. Language pack ID must start with &#039;X&#039;, consist only of English letters, digits and hyphens, and must not exceed 64 characters. Can be called before authorization.
		 * @param strings Strings of the new language pack.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetCustomLanguagePack(LanguagePackInfo info, LanguagePackString[] strings) {
			this.info = info;
			this.strings = strings;
		}

		/**
		 * Adds or changes a custom local language pack to the current localization target.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetCustomLanguagePack(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (LanguagePackInfo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.info = new LanguagePackInfo(input);
			}
			if (input.readBoolean()) {
				this.strings = new LanguagePackString[input.readInt()];
				for (int i = 0; i < this.strings.length; i++) {
					if (LanguagePackString.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.strings[i] = new LanguagePackString(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetCustomLanguagePack.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetCustomLanguagePack.CONSTRUCTOR);
			if (this.info == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.info.serialize(output);
			}
			if (this.strings == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.strings.length);
				for (int i = 0; i < this.strings.length; i++) {
					this.strings[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetCustomLanguagePack setCustomLanguagePack = (SetCustomLanguagePack) o;
			if (!Objects.equals(this.info, setCustomLanguagePack.info)) {
				return false;
			}
			if (!Arrays.equals(this.strings, setCustomLanguagePack.strings)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.info == null ? 0 : this.info.hashCode();
			result = result * 31 + (Arrays.hashCode(this.strings));
			return result;
		}
	}

	/**
	 * Adds, edits or deletes a string in a custom local language pack. Can
	 * be called before authorization.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetCustomLanguagePackString extends Function<Ok> {


		/**
		 * Identifier of a previously added custom local language pack in the current localization target.
		**/
		public String languagePackId;

		/**
		 * New language pack string.
		**/
		public LanguagePackString newString;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1316365592;

		/**
		 * Adds, edits or deletes a string in a custom local language pack. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetCustomLanguagePackString() {}

		/**
		 * Adds, edits or deletes a string in a custom local language pack. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param languagePackId Identifier of a previously added custom local language pack in the current localization target.
		 * @param newString New language pack string.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetCustomLanguagePackString(String languagePackId, LanguagePackString newString) {
			this.languagePackId = languagePackId;
			this.newString = newString;
		}

		/**
		 * Adds, edits or deletes a string in a custom local language pack. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetCustomLanguagePackString(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] languagePackIdTmp = new byte[input.readInt()];
				input.readFully(languagePackIdTmp);
				this.languagePackId = new String(languagePackIdTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				if (LanguagePackString.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.newString = new LanguagePackString(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetCustomLanguagePackString.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetCustomLanguagePackString.CONSTRUCTOR);
			if (this.languagePackId == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] languagePackIdTmp = this.languagePackId.getBytes(StandardCharsets.UTF_8);
				output.writeInt(languagePackIdTmp.length);
				output.write(languagePackIdTmp);
			}
			if (this.newString == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.newString.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetCustomLanguagePackString setCustomLanguagePackString = (SetCustomLanguagePackString) o;
			if (this.languagePackId != setCustomLanguagePackString.languagePackId) {
				return false;
			}
			if (!Objects.equals(this.newString, setCustomLanguagePackString.newString)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.languagePackId == null ? 0 : this.languagePackId.hashCode();
			result = result * 31 + (this.newString == null ? 0 : this.newString.hashCode());
			return result;
		}
	}

	/**
	 * Changes the database encryption key. Usually the encryption key is
	 * never changed and is stored in some OS keychain.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetDatabaseEncryptionKey extends Function<Ok> {


		/**
		 * New encryption key.
		**/
		public byte[] newEncryptionKey;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1204599371;

		/**
		 * Changes the database encryption key. Usually the encryption key is never changed and is stored in some OS keychain.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetDatabaseEncryptionKey() {}

		/**
		 * Changes the database encryption key. Usually the encryption key is never changed and is stored in some OS keychain.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param newEncryptionKey New encryption key.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetDatabaseEncryptionKey(byte[] newEncryptionKey) {
			this.newEncryptionKey = newEncryptionKey;
		}

		/**
		 * Changes the database encryption key. Usually the encryption key is never changed and is stored in some OS keychain.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetDatabaseEncryptionKey(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.newEncryptionKey = new byte[input.readInt()];
				input.readFully(this.newEncryptionKey);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetDatabaseEncryptionKey.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetDatabaseEncryptionKey.CONSTRUCTOR);
			if (this.newEncryptionKey == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.newEncryptionKey.length);
				output.write(this.newEncryptionKey);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetDatabaseEncryptionKey setDatabaseEncryptionKey = (SetDatabaseEncryptionKey) o;
			if (this.newEncryptionKey != setDatabaseEncryptionKey.newEncryptionKey) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.newEncryptionKey);
		}
	}

	/**
	 * Sets default administrator rights for adding the bot to channel
	 * chats; for bots only.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetDefaultChannelAdministratorRights extends Function<Ok> {


		/**
		 * Default administrator rights for adding the bot to channels; may be null.
		**/
		public ChatAdministratorRights defaultChannelAdministratorRights;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -234004967;

		/**
		 * Sets default administrator rights for adding the bot to channel chats; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetDefaultChannelAdministratorRights() {}

		/**
		 * Sets default administrator rights for adding the bot to channel chats; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param defaultChannelAdministratorRights Default administrator rights for adding the bot to channels; may be null.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetDefaultChannelAdministratorRights(ChatAdministratorRights defaultChannelAdministratorRights) {
			this.defaultChannelAdministratorRights = defaultChannelAdministratorRights;
		}

		/**
		 * Sets default administrator rights for adding the bot to channel chats; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetDefaultChannelAdministratorRights(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (ChatAdministratorRights.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.defaultChannelAdministratorRights = new ChatAdministratorRights(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetDefaultChannelAdministratorRights.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetDefaultChannelAdministratorRights.CONSTRUCTOR);
			if (this.defaultChannelAdministratorRights == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.defaultChannelAdministratorRights.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetDefaultChannelAdministratorRights setDefaultChannelAdministratorRights = (SetDefaultChannelAdministratorRights) o;
			if (!Objects.equals(this.defaultChannelAdministratorRights, setDefaultChannelAdministratorRights.defaultChannelAdministratorRights)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.defaultChannelAdministratorRights == null ? 0 : this.defaultChannelAdministratorRights.hashCode();
		}
	}

	/**
	 * Sets default administrator rights for adding the bot to basic group
	 * and supergroup chats; for bots only.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetDefaultGroupAdministratorRights extends Function<Ok> {


		/**
		 * Default administrator rights for adding the bot to basic group and supergroup chats; may be null.
		**/
		public ChatAdministratorRights defaultGroupAdministratorRights;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1700231016;

		/**
		 * Sets default administrator rights for adding the bot to basic group and supergroup chats; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetDefaultGroupAdministratorRights() {}

		/**
		 * Sets default administrator rights for adding the bot to basic group and supergroup chats; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param defaultGroupAdministratorRights Default administrator rights for adding the bot to basic group and supergroup chats; may be null.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetDefaultGroupAdministratorRights(ChatAdministratorRights defaultGroupAdministratorRights) {
			this.defaultGroupAdministratorRights = defaultGroupAdministratorRights;
		}

		/**
		 * Sets default administrator rights for adding the bot to basic group and supergroup chats; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetDefaultGroupAdministratorRights(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (ChatAdministratorRights.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.defaultGroupAdministratorRights = new ChatAdministratorRights(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetDefaultGroupAdministratorRights.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetDefaultGroupAdministratorRights.CONSTRUCTOR);
			if (this.defaultGroupAdministratorRights == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.defaultGroupAdministratorRights.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetDefaultGroupAdministratorRights setDefaultGroupAdministratorRights = (SetDefaultGroupAdministratorRights) o;
			if (!Objects.equals(this.defaultGroupAdministratorRights, setDefaultGroupAdministratorRights.defaultGroupAdministratorRights)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.defaultGroupAdministratorRights == null ? 0 : this.defaultGroupAdministratorRights.hashCode();
		}
	}

	/**
	 * Changes the default message auto-delete time for new chats.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetDefaultMessageAutoDeleteTime extends Function<Ok> {


		/**
		 * New default message auto-delete time; must be from 0 up to 365 * 86400 and be divisible by 86400. If 0, then messages aren&#039;t deleted automatically.
		**/
		public MessageAutoDeleteTime messageAutoDeleteTime;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1772301460;

		/**
		 * Changes the default message auto-delete time for new chats.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetDefaultMessageAutoDeleteTime() {}

		/**
		 * Changes the default message auto-delete time for new chats.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param messageAutoDeleteTime New default message auto-delete time; must be from 0 up to 365 * 86400 and be divisible by 86400. If 0, then messages aren&#039;t deleted automatically.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetDefaultMessageAutoDeleteTime(MessageAutoDeleteTime messageAutoDeleteTime) {
			this.messageAutoDeleteTime = messageAutoDeleteTime;
		}

		/**
		 * Changes the default message auto-delete time for new chats.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetDefaultMessageAutoDeleteTime(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (MessageAutoDeleteTime.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.messageAutoDeleteTime = new MessageAutoDeleteTime(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetDefaultMessageAutoDeleteTime.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetDefaultMessageAutoDeleteTime.CONSTRUCTOR);
			if (this.messageAutoDeleteTime == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.messageAutoDeleteTime.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetDefaultMessageAutoDeleteTime setDefaultMessageAutoDeleteTime = (SetDefaultMessageAutoDeleteTime) o;
			if (!Objects.equals(this.messageAutoDeleteTime, setDefaultMessageAutoDeleteTime.messageAutoDeleteTime)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.messageAutoDeleteTime == null ? 0 : this.messageAutoDeleteTime.hashCode();
		}
	}

	/**
	 * Changes type of default reaction for the current user.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetDefaultReactionType extends Function<Ok> {


		/**
		 * New type of the default reaction.
		**/
		public ReactionType reactionType;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1694730813;

		/**
		 * Changes type of default reaction for the current user.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetDefaultReactionType() {}

		/**
		 * Changes type of default reaction for the current user.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param reactionType New type of the default reaction.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetDefaultReactionType(ReactionType reactionType) {
			this.reactionType = reactionType;
		}

		/**
		 * Changes type of default reaction for the current user.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetDefaultReactionType(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ReactionTypeEmoji.CONSTRUCTOR: this.reactionType = new ReactionTypeEmoji(input); break;
					case ReactionTypeCustomEmoji.CONSTRUCTOR: this.reactionType = new ReactionTypeCustomEmoji(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetDefaultReactionType.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetDefaultReactionType.CONSTRUCTOR);
			if (this.reactionType == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.reactionType.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetDefaultReactionType setDefaultReactionType = (SetDefaultReactionType) o;
			if (!Objects.equals(this.reactionType, setDefaultReactionType.reactionType)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.reactionType == null ? 0 : this.reactionType.hashCode();
		}
	}

	/**
	 * Changes the emoji status of the current user; for Telegram Premium
	 * users only.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetEmojiStatus extends Function<Ok> {


		/**
		 * New emoji status; pass null to switch to the default badge.
		**/
		public EmojiStatus emojiStatus;

		/**
		 * Duration of the status, in seconds; pass 0 to keep the status active until it will be changed manually.
		**/
		public int duration;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1310680569;

		/**
		 * Changes the emoji status of the current user; for Telegram Premium users only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetEmojiStatus() {}

		/**
		 * Changes the emoji status of the current user; for Telegram Premium users only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param emojiStatus New emoji status; pass null to switch to the default badge.
		 * @param duration Duration of the status, in seconds; pass 0 to keep the status active until it will be changed manually.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetEmojiStatus(EmojiStatus emojiStatus, int duration) {
			this.emojiStatus = emojiStatus;
			this.duration = duration;
		}

		/**
		 * Changes the emoji status of the current user; for Telegram Premium users only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetEmojiStatus(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (EmojiStatus.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.emojiStatus = new EmojiStatus(input);
			}
			this.duration = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetEmojiStatus.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetEmojiStatus.CONSTRUCTOR);
			if (this.emojiStatus == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.emojiStatus.serialize(output);
			}
			output.writeInt(this.duration);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetEmojiStatus setEmojiStatus = (SetEmojiStatus) o;
			if (!Objects.equals(this.emojiStatus, setEmojiStatus.emojiStatus)) {
				return false;
			}
			if (this.duration != setEmojiStatus.duration) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.duration);
			result = result * 31 + (this.emojiStatus == null ? 0 : this.emojiStatus.hashCode());
			return result;
		}
	}

	/**
	 * Informs TDLib on a file generation progress.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetFileGenerationProgress extends Function<Ok> {


		/**
		 * The identifier of the generation process.
		**/
		public long generationId;

		/**
		 * Expected size of the generated file, in bytes; 0 if unknown.
		**/
		public long expectedSize;

		/**
		 * The number of bytes already generated.
		**/
		public long localPrefixSize;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1836403518;

		/**
		 * Informs TDLib on a file generation progress.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetFileGenerationProgress() {}

		/**
		 * Informs TDLib on a file generation progress.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param generationId The identifier of the generation process.
		 * @param expectedSize Expected size of the generated file, in bytes; 0 if unknown.
		 * @param localPrefixSize The number of bytes already generated.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetFileGenerationProgress(long generationId, long expectedSize, long localPrefixSize) {
			this.generationId = generationId;
			this.expectedSize = expectedSize;
			this.localPrefixSize = localPrefixSize;
		}

		/**
		 * Informs TDLib on a file generation progress.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetFileGenerationProgress(DataInput input) throws IOException {
			this.generationId = input.readLong();
			this.expectedSize = input.readLong();
			this.localPrefixSize = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetFileGenerationProgress.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetFileGenerationProgress.CONSTRUCTOR);
			output.writeLong(this.generationId);
			output.writeLong(this.expectedSize);
			output.writeLong(this.localPrefixSize);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetFileGenerationProgress setFileGenerationProgress = (SetFileGenerationProgress) o;
			if (this.generationId != setFileGenerationProgress.generationId) {
				return false;
			}
			if (this.expectedSize != setFileGenerationProgress.expectedSize) {
				return false;
			}
			if (this.localPrefixSize != setFileGenerationProgress.localPrefixSize) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.generationId);
			return result;
		}
	}

	/**
	 * Changes the notification settings of a forum topic.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetForumTopicNotificationSettings extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Message thread identifier of the forum topic.
		**/
		public long messageThreadId;

		/**
		 * New notification settings for the forum topic. If the topic is muted for more than 366 days, it is considered to be muted forever.
		**/
		public ChatNotificationSettings notificationSettings;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 524498023;

		/**
		 * Changes the notification settings of a forum topic.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetForumTopicNotificationSettings() {}

		/**
		 * Changes the notification settings of a forum topic.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param messageThreadId Message thread identifier of the forum topic.
		 * @param notificationSettings New notification settings for the forum topic. If the topic is muted for more than 366 days, it is considered to be muted forever.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetForumTopicNotificationSettings(long chatId,
				long messageThreadId,
				ChatNotificationSettings notificationSettings) {
			this.chatId = chatId;
			this.messageThreadId = messageThreadId;
			this.notificationSettings = notificationSettings;
		}

		/**
		 * Changes the notification settings of a forum topic.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetForumTopicNotificationSettings(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageThreadId = input.readLong();
			if (input.readBoolean()) {
				if (ChatNotificationSettings.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.notificationSettings = new ChatNotificationSettings(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetForumTopicNotificationSettings.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetForumTopicNotificationSettings.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageThreadId);
			if (this.notificationSettings == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.notificationSettings.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetForumTopicNotificationSettings setForumTopicNotificationSettings = (SetForumTopicNotificationSettings) o;
			if (this.chatId != setForumTopicNotificationSettings.chatId) {
				return false;
			}
			if (this.messageThreadId != setForumTopicNotificationSettings.messageThreadId) {
				return false;
			}
			if (!Objects.equals(this.notificationSettings, setForumTopicNotificationSettings.notificationSettings)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.notificationSettings == null ? 0 : this.notificationSettings.hashCode());
			return result;
		}
	}

	/**
	 * Updates the game score of the specified user in the game; for bots
	 * only.
	 * <p> Returns {@link Message Message} </p>
	**/
	public static final class SetGameScore extends Function<Message> {


		/**
		 * The chat to which the message with the game belongs.
		**/
		public long chatId;

		/**
		 * Identifier of the message.
		**/
		public long messageId;

		/**
		 * Pass true to edit the game message to include the current scoreboard.
		**/
		public boolean editMessage;

		/**
		 * User identifier.
		**/
		public long userId;

		/**
		 * The new score.
		**/
		public int score;

		/**
		 * Pass true to update the score even if it decreases. If the score is 0, the user will be deleted from the high score table.
		**/
		public boolean force;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2127359430;

		/**
		 * Updates the game score of the specified user in the game; for bots only.
		 *
		 * <p> Returns {@link Message Message} </p>
		**/
		public SetGameScore() {}

		/**
		 * Updates the game score of the specified user in the game; for bots only.
		 *
		 * <p> Returns {@link Message Message} </p>
		 *
		 * @param chatId The chat to which the message with the game belongs.
		 * @param messageId Identifier of the message.
		 * @param editMessage Pass true to edit the game message to include the current scoreboard.
		 * @param userId User identifier.
		 * @param score The new score.
		 * @param force Pass true to update the score even if it decreases. If the score is 0, the user will be deleted from the high score table.
		 *
		 * <p> Returns {@link Message Message} </p>
		**/
		public SetGameScore(long chatId,
				long messageId,
				boolean editMessage,
				long userId,
				int score,
				boolean force) {
			this.chatId = chatId;
			this.messageId = messageId;
			this.editMessage = editMessage;
			this.userId = userId;
			this.score = score;
			this.force = force;
		}

		/**
		 * Updates the game score of the specified user in the game; for bots only.
		 *
		 * <p> Returns {@link Message Message} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetGameScore(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
			this.editMessage = input.readBoolean();
			this.userId = input.readLong();
			this.score = input.readInt();
			this.force = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetGameScore.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetGameScore.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
			output.writeBoolean(this.editMessage);
			output.writeLong(this.userId);
			output.writeInt(this.score);
			output.writeBoolean(this.force);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetGameScore setGameScore = (SetGameScore) o;
			if (this.chatId != setGameScore.chatId) {
				return false;
			}
			if (this.messageId != setGameScore.messageId) {
				return false;
			}
			if (this.editMessage != setGameScore.editMessage) {
				return false;
			}
			if (this.userId != setGameScore.userId) {
				return false;
			}
			if (this.score != setGameScore.score) {
				return false;
			}
			if (this.force != setGameScore.force) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Informs TDLib that speaking state of a participant of an active group
	 * has changed.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetGroupCallParticipantIsSpeaking extends Function<Ok> {


		/**
		 * Group call identifier.
		**/
		public int groupCallId;

		/**
		 * Group call participant&#039;s synchronization audio source identifier, or 0 for the current user.
		**/
		public int audioSource;

		/**
		 * Pass true if the user is speaking.
		**/
		public boolean isSpeaking;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 927506917;

		/**
		 * Informs TDLib that speaking state of a participant of an active group has changed.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetGroupCallParticipantIsSpeaking() {}

		/**
		 * Informs TDLib that speaking state of a participant of an active group has changed.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param groupCallId Group call identifier.
		 * @param audioSource Group call participant&#039;s synchronization audio source identifier, or 0 for the current user.
		 * @param isSpeaking Pass true if the user is speaking.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetGroupCallParticipantIsSpeaking(int groupCallId, int audioSource, boolean isSpeaking) {
			this.groupCallId = groupCallId;
			this.audioSource = audioSource;
			this.isSpeaking = isSpeaking;
		}

		/**
		 * Informs TDLib that speaking state of a participant of an active group has changed.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetGroupCallParticipantIsSpeaking(DataInput input) throws IOException {
			this.groupCallId = input.readInt();
			this.audioSource = input.readInt();
			this.isSpeaking = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetGroupCallParticipantIsSpeaking.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetGroupCallParticipantIsSpeaking.CONSTRUCTOR);
			output.writeInt(this.groupCallId);
			output.writeInt(this.audioSource);
			output.writeBoolean(this.isSpeaking);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetGroupCallParticipantIsSpeaking setGroupCallParticipantIsSpeaking = (SetGroupCallParticipantIsSpeaking) o;
			if (this.groupCallId != setGroupCallParticipantIsSpeaking.groupCallId) {
				return false;
			}
			if (this.audioSource != setGroupCallParticipantIsSpeaking.audioSource) {
				return false;
			}
			if (this.isSpeaking != setGroupCallParticipantIsSpeaking.isSpeaking) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.groupCallId);
			return result;
		}
	}

	/**
	 * Changes volume level of a participant of an active group call. If the
	 * current user can manage the group call, then the participant&#039;s
	 * volume level will be changed for all users with the default volume
	 * level.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetGroupCallParticipantVolumeLevel extends Function<Ok> {


		/**
		 * Group call identifier.
		**/
		public int groupCallId;

		/**
		 * Participant identifier.
		**/
		public MessageSender participantId;

		/**
		 * New participant&#039;s volume level; 1-20000 in hundreds of percents.
		**/
		public int volumeLevel;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1753769944;

		/**
		 * Changes volume level of a participant of an active group call. If the current user can manage the group call, then the participant&#039;s volume level will be changed for all users with the default volume level.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetGroupCallParticipantVolumeLevel() {}

		/**
		 * Changes volume level of a participant of an active group call. If the current user can manage the group call, then the participant&#039;s volume level will be changed for all users with the default volume level.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param groupCallId Group call identifier.
		 * @param participantId Participant identifier.
		 * @param volumeLevel New participant&#039;s volume level; 1-20000 in hundreds of percents.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetGroupCallParticipantVolumeLevel(int groupCallId,
				MessageSender participantId,
				int volumeLevel) {
			this.groupCallId = groupCallId;
			this.participantId = participantId;
			this.volumeLevel = volumeLevel;
		}

		/**
		 * Changes volume level of a participant of an active group call. If the current user can manage the group call, then the participant&#039;s volume level will be changed for all users with the default volume level.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetGroupCallParticipantVolumeLevel(DataInput input) throws IOException {
			this.groupCallId = input.readInt();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case MessageSenderUser.CONSTRUCTOR: this.participantId = new MessageSenderUser(input); break;
					case MessageSenderChat.CONSTRUCTOR: this.participantId = new MessageSenderChat(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.volumeLevel = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetGroupCallParticipantVolumeLevel.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetGroupCallParticipantVolumeLevel.CONSTRUCTOR);
			output.writeInt(this.groupCallId);
			if (this.participantId == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.participantId.serialize(output);
			}
			output.writeInt(this.volumeLevel);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetGroupCallParticipantVolumeLevel setGroupCallParticipantVolumeLevel = (SetGroupCallParticipantVolumeLevel) o;
			if (this.groupCallId != setGroupCallParticipantVolumeLevel.groupCallId) {
				return false;
			}
			if (!Objects.equals(this.participantId, setGroupCallParticipantVolumeLevel.participantId)) {
				return false;
			}
			if (this.volumeLevel != setGroupCallParticipantVolumeLevel.volumeLevel) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.groupCallId);
			result = result * 31 + (this.participantId == null ? 0 : this.participantId.hashCode());
			return result;
		}
	}

	/**
	 * Sets group call title. Requires groupCall.canBeManaged group call
	 * flag.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetGroupCallTitle extends Function<Ok> {


		/**
		 * Group call identifier.
		**/
		public int groupCallId;

		/**
		 * New group call title; 1-64 characters.
		**/
		public String title;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1228825139;

		/**
		 * Sets group call title. Requires groupCall.canBeManaged group call flag.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetGroupCallTitle() {}

		/**
		 * Sets group call title. Requires groupCall.canBeManaged group call flag.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param groupCallId Group call identifier.
		 * @param title New group call title; 1-64 characters.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetGroupCallTitle(int groupCallId, String title) {
			this.groupCallId = groupCallId;
			this.title = title;
		}

		/**
		 * Sets group call title. Requires groupCall.canBeManaged group call flag.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetGroupCallTitle(DataInput input) throws IOException {
			this.groupCallId = input.readInt();
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetGroupCallTitle.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetGroupCallTitle.CONSTRUCTOR);
			output.writeInt(this.groupCallId);
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetGroupCallTitle setGroupCallTitle = (SetGroupCallTitle) o;
			if (this.groupCallId != setGroupCallTitle.groupCallId) {
				return false;
			}
			if (this.title != setGroupCallTitle.title) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.groupCallId);
			result = result * 31 + (this.title == null ? 0 : this.title.hashCode());
			return result;
		}
	}

	/**
	 * Changes the period of inactivity after which sessions will
	 * automatically be terminated.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetInactiveSessionTtl extends Function<Ok> {


		/**
		 * New number of days of inactivity before sessions will be automatically terminated; 1-366 days.
		**/
		public int inactiveSessionTtlDays;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1570548048;

		/**
		 * Changes the period of inactivity after which sessions will automatically be terminated.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetInactiveSessionTtl() {}

		/**
		 * Changes the period of inactivity after which sessions will automatically be terminated.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param inactiveSessionTtlDays New number of days of inactivity before sessions will be automatically terminated; 1-366 days.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetInactiveSessionTtl(int inactiveSessionTtlDays) {
			this.inactiveSessionTtlDays = inactiveSessionTtlDays;
		}

		/**
		 * Changes the period of inactivity after which sessions will automatically be terminated.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetInactiveSessionTtl(DataInput input) throws IOException {
			this.inactiveSessionTtlDays = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetInactiveSessionTtl.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetInactiveSessionTtl.CONSTRUCTOR);
			output.writeInt(this.inactiveSessionTtlDays);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetInactiveSessionTtl setInactiveSessionTtl = (SetInactiveSessionTtl) o;
			if (this.inactiveSessionTtlDays != setInactiveSessionTtl.inactiveSessionTtlDays) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.inactiveSessionTtlDays);
		}
	}

	/**
	 * Updates the game score of the specified user in a game; for bots only.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetInlineGameScore extends Function<Ok> {


		/**
		 * Inline message identifier.
		**/
		public String inlineMessageId;

		/**
		 * Pass true to edit the game message to include the current scoreboard.
		**/
		public boolean editMessage;

		/**
		 * User identifier.
		**/
		public long userId;

		/**
		 * The new score.
		**/
		public int score;

		/**
		 * Pass true to update the score even if it decreases. If the score is 0, the user will be deleted from the high score table.
		**/
		public boolean force;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -948871797;

		/**
		 * Updates the game score of the specified user in a game; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetInlineGameScore() {}

		/**
		 * Updates the game score of the specified user in a game; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param inlineMessageId Inline message identifier.
		 * @param editMessage Pass true to edit the game message to include the current scoreboard.
		 * @param userId User identifier.
		 * @param score The new score.
		 * @param force Pass true to update the score even if it decreases. If the score is 0, the user will be deleted from the high score table.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetInlineGameScore(String inlineMessageId,
				boolean editMessage,
				long userId,
				int score,
				boolean force) {
			this.inlineMessageId = inlineMessageId;
			this.editMessage = editMessage;
			this.userId = userId;
			this.score = score;
			this.force = force;
		}

		/**
		 * Updates the game score of the specified user in a game; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetInlineGameScore(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] inlineMessageIdTmp = new byte[input.readInt()];
				input.readFully(inlineMessageIdTmp);
				this.inlineMessageId = new String(inlineMessageIdTmp, StandardCharsets.UTF_8);
			}
			this.editMessage = input.readBoolean();
			this.userId = input.readLong();
			this.score = input.readInt();
			this.force = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetInlineGameScore.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetInlineGameScore.CONSTRUCTOR);
			if (this.inlineMessageId == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] inlineMessageIdTmp = this.inlineMessageId.getBytes(StandardCharsets.UTF_8);
				output.writeInt(inlineMessageIdTmp.length);
				output.write(inlineMessageIdTmp);
			}
			output.writeBoolean(this.editMessage);
			output.writeLong(this.userId);
			output.writeInt(this.score);
			output.writeBoolean(this.force);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetInlineGameScore setInlineGameScore = (SetInlineGameScore) o;
			if (this.inlineMessageId != setInlineGameScore.inlineMessageId) {
				return false;
			}
			if (this.editMessage != setInlineGameScore.editMessage) {
				return false;
			}
			if (this.userId != setInlineGameScore.userId) {
				return false;
			}
			if (this.score != setInlineGameScore.score) {
				return false;
			}
			if (this.force != setInlineGameScore.force) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.editMessage);
			result = result * 31 + (this.inlineMessageId == null ? 0 : this.inlineMessageId.hashCode());
			return result;
		}
	}

	/**
	 * Changes the location of the current user. Needs to be called if
	 * getOption(&quot;is_location_visible&quot;) is true and location
	 * changes for more than 1 kilometer.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetLocation extends Function<Ok> {


		/**
		 * The new location of the user.
		**/
		public Location location;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 93926257;

		/**
		 * Changes the location of the current user. Needs to be called if getOption(&quot;is_location_visible&quot;) is true and location changes for more than 1 kilometer.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetLocation() {}

		/**
		 * Changes the location of the current user. Needs to be called if getOption(&quot;is_location_visible&quot;) is true and location changes for more than 1 kilometer.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param location The new location of the user.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetLocation(Location location) {
			this.location = location;
		}

		/**
		 * Changes the location of the current user. Needs to be called if getOption(&quot;is_location_visible&quot;) is true and location changes for more than 1 kilometer.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetLocation(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Location.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.location = new Location(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetLocation.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetLocation.CONSTRUCTOR);
			if (this.location == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.location.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetLocation setLocation = (SetLocation) o;
			if (!Objects.equals(this.location, setLocation.location)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.location == null ? 0 : this.location.hashCode();
		}
	}

	/**
	 * Sets new log stream for internal logging of TDLib. Can be called
	 * synchronously.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetLogStream extends Function<Ok> {


		/**
		 * New log stream.
		**/
		public LogStream logStream;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1364199535;

		/**
		 * Sets new log stream for internal logging of TDLib. Can be called synchronously.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetLogStream() {}

		/**
		 * Sets new log stream for internal logging of TDLib. Can be called synchronously.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param logStream New log stream.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetLogStream(LogStream logStream) {
			this.logStream = logStream;
		}

		/**
		 * Sets new log stream for internal logging of TDLib. Can be called synchronously.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetLogStream(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case LogStreamDefault.CONSTRUCTOR: this.logStream = new LogStreamDefault(input); break;
					case LogStreamFile.CONSTRUCTOR: this.logStream = new LogStreamFile(input); break;
					case LogStreamEmpty.CONSTRUCTOR: this.logStream = new LogStreamEmpty(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetLogStream.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetLogStream.CONSTRUCTOR);
			if (this.logStream == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.logStream.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetLogStream setLogStream = (SetLogStream) o;
			if (!Objects.equals(this.logStream, setLogStream.logStream)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.logStream == null ? 0 : this.logStream.hashCode();
		}
	}

	/**
	 * Sets the verbosity level for a specified TDLib internal log tag. Can
	 * be called synchronously.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetLogTagVerbosityLevel extends Function<Ok> {


		/**
		 * Logging tag to change verbosity level.
		**/
		public String tag;

		/**
		 * New verbosity level; 1-1024.
		**/
		public int newVerbosityLevel;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2095589738;

		/**
		 * Sets the verbosity level for a specified TDLib internal log tag. Can be called synchronously.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetLogTagVerbosityLevel() {}

		/**
		 * Sets the verbosity level for a specified TDLib internal log tag. Can be called synchronously.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param tag Logging tag to change verbosity level.
		 * @param newVerbosityLevel New verbosity level; 1-1024.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetLogTagVerbosityLevel(String tag, int newVerbosityLevel) {
			this.tag = tag;
			this.newVerbosityLevel = newVerbosityLevel;
		}

		/**
		 * Sets the verbosity level for a specified TDLib internal log tag. Can be called synchronously.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetLogTagVerbosityLevel(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] tagTmp = new byte[input.readInt()];
				input.readFully(tagTmp);
				this.tag = new String(tagTmp, StandardCharsets.UTF_8);
			}
			this.newVerbosityLevel = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetLogTagVerbosityLevel.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetLogTagVerbosityLevel.CONSTRUCTOR);
			if (this.tag == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] tagTmp = this.tag.getBytes(StandardCharsets.UTF_8);
				output.writeInt(tagTmp.length);
				output.write(tagTmp);
			}
			output.writeInt(this.newVerbosityLevel);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetLogTagVerbosityLevel setLogTagVerbosityLevel = (SetLogTagVerbosityLevel) o;
			if (this.tag != setLogTagVerbosityLevel.tag) {
				return false;
			}
			if (this.newVerbosityLevel != setLogTagVerbosityLevel.newVerbosityLevel) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.newVerbosityLevel);
			result = result * 31 + (this.tag == null ? 0 : this.tag.hashCode());
			return result;
		}
	}

	/**
	 * Sets the verbosity level of the internal logging of TDLib. Can be
	 * called synchronously.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetLogVerbosityLevel extends Function<Ok> {


		/**
		 * New value of the verbosity level for logging. Value 0 corresponds to fatal errors, value 1 corresponds to errors, value 2 corresponds to warnings and debug warnings, value 3 corresponds to informational, value 4 corresponds to debug, value 5 corresponds to verbose debug, value greater than 5 and up to 1023 can be used to enable even more logging.
		**/
		public int newVerbosityLevel;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -303429678;

		/**
		 * Sets the verbosity level of the internal logging of TDLib. Can be called synchronously.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetLogVerbosityLevel() {}

		/**
		 * Sets the verbosity level of the internal logging of TDLib. Can be called synchronously.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param newVerbosityLevel New value of the verbosity level for logging. Value 0 corresponds to fatal errors, value 1 corresponds to errors, value 2 corresponds to warnings and debug warnings, value 3 corresponds to informational, value 4 corresponds to debug, value 5 corresponds to verbose debug, value greater than 5 and up to 1023 can be used to enable even more logging.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetLogVerbosityLevel(int newVerbosityLevel) {
			this.newVerbosityLevel = newVerbosityLevel;
		}

		/**
		 * Sets the verbosity level of the internal logging of TDLib. Can be called synchronously.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetLogVerbosityLevel(DataInput input) throws IOException {
			this.newVerbosityLevel = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetLogVerbosityLevel.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetLogVerbosityLevel.CONSTRUCTOR);
			output.writeInt(this.newVerbosityLevel);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetLogVerbosityLevel setLogVerbosityLevel = (SetLogVerbosityLevel) o;
			if (this.newVerbosityLevel != setLogVerbosityLevel.newVerbosityLevel) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.newVerbosityLevel);
		}
	}

	/**
	 * Changes the login email address of the user. The email address can be
	 * changed only if the current user already has login email and
	 * passwordState.loginEmailAddressPattern is non-empty. The change will
	 * not be applied until the new login email address is confirmed with
	 * checkLoginEmailAddressCode. To use Apple ID/Google ID instead of a
	 * email address, call checkLoginEmailAddressCode directly.
	 * <p> Returns {@link EmailAddressAuthenticationCodeInfo
	 * EmailAddressAuthenticationCodeInfo} </p>
	**/
	public static final class SetLoginEmailAddress extends Function<EmailAddressAuthenticationCodeInfo> {


		/**
		 * New login email address.
		**/
		public String newLoginEmailAddress;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 935019476;

		/**
		 * Changes the login email address of the user. The email address can be changed only if the current user already has login email and passwordState.loginEmailAddressPattern is non-empty. The change will not be applied until the new login email address is confirmed with checkLoginEmailAddressCode. To use Apple ID/Google ID instead of a email address, call checkLoginEmailAddressCode directly.
		 *
		 * <p> Returns {@link EmailAddressAuthenticationCodeInfo EmailAddressAuthenticationCodeInfo} </p>
		**/
		public SetLoginEmailAddress() {}

		/**
		 * Changes the login email address of the user. The email address can be changed only if the current user already has login email and passwordState.loginEmailAddressPattern is non-empty. The change will not be applied until the new login email address is confirmed with checkLoginEmailAddressCode. To use Apple ID/Google ID instead of a email address, call checkLoginEmailAddressCode directly.
		 *
		 * <p> Returns {@link EmailAddressAuthenticationCodeInfo EmailAddressAuthenticationCodeInfo} </p>
		 *
		 * @param newLoginEmailAddress New login email address.
		 *
		 * <p> Returns {@link EmailAddressAuthenticationCodeInfo EmailAddressAuthenticationCodeInfo} </p>
		**/
		public SetLoginEmailAddress(String newLoginEmailAddress) {
			this.newLoginEmailAddress = newLoginEmailAddress;
		}

		/**
		 * Changes the login email address of the user. The email address can be changed only if the current user already has login email and passwordState.loginEmailAddressPattern is non-empty. The change will not be applied until the new login email address is confirmed with checkLoginEmailAddressCode. To use Apple ID/Google ID instead of a email address, call checkLoginEmailAddressCode directly.
		 *
		 * <p> Returns {@link EmailAddressAuthenticationCodeInfo EmailAddressAuthenticationCodeInfo} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetLoginEmailAddress(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] newLoginEmailAddressTmp = new byte[input.readInt()];
				input.readFully(newLoginEmailAddressTmp);
				this.newLoginEmailAddress = new String(newLoginEmailAddressTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetLoginEmailAddress.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetLoginEmailAddress.CONSTRUCTOR);
			if (this.newLoginEmailAddress == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] newLoginEmailAddressTmp = this.newLoginEmailAddress.getBytes(StandardCharsets.UTF_8);
				output.writeInt(newLoginEmailAddressTmp.length);
				output.write(newLoginEmailAddressTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetLoginEmailAddress setLoginEmailAddress = (SetLoginEmailAddress) o;
			if (this.newLoginEmailAddress != setLoginEmailAddress.newLoginEmailAddress) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.newLoginEmailAddress == null ? 0 : this.newLoginEmailAddress.hashCode();
		}
	}

	/**
	 * Sets menu button for the given user or for all users; for bots only.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetMenuButton extends Function<Ok> {


		/**
		 * Identifier of the user or 0 to set menu button for all users.
		**/
		public long userId;

		/**
		 * New menu button.
		**/
		public BotMenuButton menuButton;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1269841599;

		/**
		 * Sets menu button for the given user or for all users; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetMenuButton() {}

		/**
		 * Sets menu button for the given user or for all users; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param userId Identifier of the user or 0 to set menu button for all users.
		 * @param menuButton New menu button.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetMenuButton(long userId, BotMenuButton menuButton) {
			this.userId = userId;
			this.menuButton = menuButton;
		}

		/**
		 * Sets menu button for the given user or for all users; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetMenuButton(DataInput input) throws IOException {
			this.userId = input.readLong();
			if (input.readBoolean()) {
				if (BotMenuButton.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.menuButton = new BotMenuButton(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetMenuButton.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetMenuButton.CONSTRUCTOR);
			output.writeLong(this.userId);
			if (this.menuButton == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.menuButton.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetMenuButton setMenuButton = (SetMenuButton) o;
			if (this.userId != setMenuButton.userId) {
				return false;
			}
			if (!Objects.equals(this.menuButton, setMenuButton.menuButton)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.userId);
			result = result * 31 + (this.menuButton == null ? 0 : this.menuButton.hashCode());
			return result;
		}
	}

	/**
	 * Changes the first and last name of the current user.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetName extends Function<Ok> {


		/**
		 * The new value of the first name for the current user; 1-64 characters.
		**/
		public String firstName;

		/**
		 * The new value of the optional last name for the current user; 0-64 characters.
		**/
		public String lastName;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1711693584;

		/**
		 * Changes the first and last name of the current user.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetName() {}

		/**
		 * Changes the first and last name of the current user.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param firstName The new value of the first name for the current user; 1-64 characters.
		 * @param lastName The new value of the optional last name for the current user; 0-64 characters.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetName(String firstName, String lastName) {
			this.firstName = firstName;
			this.lastName = lastName;
		}

		/**
		 * Changes the first and last name of the current user.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetName(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] firstNameTmp = new byte[input.readInt()];
				input.readFully(firstNameTmp);
				this.firstName = new String(firstNameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] lastNameTmp = new byte[input.readInt()];
				input.readFully(lastNameTmp);
				this.lastName = new String(lastNameTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetName.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetName.CONSTRUCTOR);
			if (this.firstName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] firstNameTmp = this.firstName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(firstNameTmp.length);
				output.write(firstNameTmp);
			}
			if (this.lastName == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] lastNameTmp = this.lastName.getBytes(StandardCharsets.UTF_8);
				output.writeInt(lastNameTmp.length);
				output.write(lastNameTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetName setName = (SetName) o;
			if (this.firstName != setName.firstName) {
				return false;
			}
			if (this.lastName != setName.lastName) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.firstName == null ? 0 : this.firstName.hashCode();
			result = result * 31 + (this.lastName == null ? 0 : this.lastName.hashCode());
			return result;
		}
	}

	/**
	 * Sets the current network type. Can be called before authorization.
	 * Calling this method forces all network connections to reopen,
	 * mitigating the delay in switching between different networks, so it
	 * must be called whenever the network is changed, even if the network
	 * type remains the same. Network type is used to check whether the
	 * library can use the network at all and also for collecting detailed
	 * network data usage statistics.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetNetworkType extends Function<Ok> {


		/**
		 * The new network type; pass null to set network type to networkTypeOther.
		**/
		public NetworkType type;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -701635234;

		/**
		 * Sets the current network type. Can be called before authorization. Calling this method forces all network connections to reopen, mitigating the delay in switching between different networks, so it must be called whenever the network is changed, even if the network type remains the same. Network type is used to check whether the library can use the network at all and also for collecting detailed network data usage statistics.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetNetworkType() {}

		/**
		 * Sets the current network type. Can be called before authorization. Calling this method forces all network connections to reopen, mitigating the delay in switching between different networks, so it must be called whenever the network is changed, even if the network type remains the same. Network type is used to check whether the library can use the network at all and also for collecting detailed network data usage statistics.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param type The new network type; pass null to set network type to networkTypeOther.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetNetworkType(NetworkType type) {
			this.type = type;
		}

		/**
		 * Sets the current network type. Can be called before authorization. Calling this method forces all network connections to reopen, mitigating the delay in switching between different networks, so it must be called whenever the network is changed, even if the network type remains the same. Network type is used to check whether the library can use the network at all and also for collecting detailed network data usage statistics.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetNetworkType(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case NetworkTypeNone.CONSTRUCTOR: this.type = new NetworkTypeNone(input); break;
					case NetworkTypeMobile.CONSTRUCTOR: this.type = new NetworkTypeMobile(input); break;
					case NetworkTypeMobileRoaming.CONSTRUCTOR: this.type = new NetworkTypeMobileRoaming(input); break;
					case NetworkTypeWiFi.CONSTRUCTOR: this.type = new NetworkTypeWiFi(input); break;
					case NetworkTypeOther.CONSTRUCTOR: this.type = new NetworkTypeOther(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetNetworkType.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetNetworkType.CONSTRUCTOR);
			if (this.type == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.type.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetNetworkType setNetworkType = (SetNetworkType) o;
			if (!Objects.equals(this.type, setNetworkType.type)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.type == null ? 0 : this.type.hashCode();
		}
	}

	/**
	 * Sets the value of an option. (Check the list of available options on
	 * https://core.telegram.org/tdlib/options.) Only writable options can
	 * be set. Can be called before authorization.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetOption extends Function<Ok> {


		/**
		 * The name of the option.
		**/
		public String name;

		/**
		 * The new value of the option; pass null to reset option value to a default value.
		**/
		public OptionValue value;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2114670322;

		/**
		 * Sets the value of an option. (Check the list of available options on https://core.telegram.org/tdlib/options.) Only writable options can be set. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetOption() {}

		/**
		 * Sets the value of an option. (Check the list of available options on https://core.telegram.org/tdlib/options.) Only writable options can be set. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param name The name of the option.
		 * @param value The new value of the option; pass null to reset option value to a default value.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetOption(String name, OptionValue value) {
			this.name = name;
			this.value = value;
		}

		/**
		 * Sets the value of an option. (Check the list of available options on https://core.telegram.org/tdlib/options.) Only writable options can be set. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetOption(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] nameTmp = new byte[input.readInt()];
				input.readFully(nameTmp);
				this.name = new String(nameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case OptionValueBoolean.CONSTRUCTOR: this.value = new OptionValueBoolean(input); break;
					case OptionValueEmpty.CONSTRUCTOR: this.value = new OptionValueEmpty(input); break;
					case OptionValueInteger.CONSTRUCTOR: this.value = new OptionValueInteger(input); break;
					case OptionValueString.CONSTRUCTOR: this.value = new OptionValueString(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetOption.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetOption.CONSTRUCTOR);
			if (this.name == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nameTmp = this.name.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nameTmp.length);
				output.write(nameTmp);
			}
			if (this.value == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.value.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetOption setOption = (SetOption) o;
			if (this.name != setOption.name) {
				return false;
			}
			if (!Objects.equals(this.value, setOption.value)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.name == null ? 0 : this.name.hashCode();
			result = result * 31 + (this.value == null ? 0 : this.value.hashCode());
			return result;
		}
	}

	/**
	 * Adds an element to the user&#039;s Telegram Passport. May return an
	 * error with a message &quot;PHONE_VERIFICATION_NEEDED&quot; or
	 * &quot;EMAIL_VERIFICATION_NEEDED&quot; if the chosen phone number or
	 * the chosen email address must be verified first.
	 * <p> Returns {@link PassportElement PassportElement} </p>
	**/
	public static final class SetPassportElement extends Function<PassportElement> {


		/**
		 * Input Telegram Passport element.
		**/
		public InputPassportElement element;

		/**
		 * The 2-step verification password of the current user.
		**/
		public String password;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2068173212;

		/**
		 * Adds an element to the user&#039;s Telegram Passport. May return an error with a message &quot;PHONE_VERIFICATION_NEEDED&quot; or &quot;EMAIL_VERIFICATION_NEEDED&quot; if the chosen phone number or the chosen email address must be verified first.
		 *
		 * <p> Returns {@link PassportElement PassportElement} </p>
		**/
		public SetPassportElement() {}

		/**
		 * Adds an element to the user&#039;s Telegram Passport. May return an error with a message &quot;PHONE_VERIFICATION_NEEDED&quot; or &quot;EMAIL_VERIFICATION_NEEDED&quot; if the chosen phone number or the chosen email address must be verified first.
		 *
		 * <p> Returns {@link PassportElement PassportElement} </p>
		 *
		 * @param element Input Telegram Passport element.
		 * @param password The 2-step verification password of the current user.
		 *
		 * <p> Returns {@link PassportElement PassportElement} </p>
		**/
		public SetPassportElement(InputPassportElement element, String password) {
			this.element = element;
			this.password = password;
		}

		/**
		 * Adds an element to the user&#039;s Telegram Passport. May return an error with a message &quot;PHONE_VERIFICATION_NEEDED&quot; or &quot;EMAIL_VERIFICATION_NEEDED&quot; if the chosen phone number or the chosen email address must be verified first.
		 *
		 * <p> Returns {@link PassportElement PassportElement} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetPassportElement(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputPassportElementPersonalDetails.CONSTRUCTOR: this.element = new InputPassportElementPersonalDetails(input); break;
					case InputPassportElementPassport.CONSTRUCTOR: this.element = new InputPassportElementPassport(input); break;
					case InputPassportElementDriverLicense.CONSTRUCTOR: this.element = new InputPassportElementDriverLicense(input); break;
					case InputPassportElementIdentityCard.CONSTRUCTOR: this.element = new InputPassportElementIdentityCard(input); break;
					case InputPassportElementInternalPassport.CONSTRUCTOR: this.element = new InputPassportElementInternalPassport(input); break;
					case InputPassportElementAddress.CONSTRUCTOR: this.element = new InputPassportElementAddress(input); break;
					case InputPassportElementUtilityBill.CONSTRUCTOR: this.element = new InputPassportElementUtilityBill(input); break;
					case InputPassportElementBankStatement.CONSTRUCTOR: this.element = new InputPassportElementBankStatement(input); break;
					case InputPassportElementRentalAgreement.CONSTRUCTOR: this.element = new InputPassportElementRentalAgreement(input); break;
					case InputPassportElementPassportRegistration.CONSTRUCTOR: this.element = new InputPassportElementPassportRegistration(input); break;
					case InputPassportElementTemporaryRegistration.CONSTRUCTOR: this.element = new InputPassportElementTemporaryRegistration(input); break;
					case InputPassportElementPhoneNumber.CONSTRUCTOR: this.element = new InputPassportElementPhoneNumber(input); break;
					case InputPassportElementEmailAddress.CONSTRUCTOR: this.element = new InputPassportElementEmailAddress(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				byte[] passwordTmp = new byte[input.readInt()];
				input.readFully(passwordTmp);
				this.password = new String(passwordTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetPassportElement.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetPassportElement.CONSTRUCTOR);
			if (this.element == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.element.serialize(output);
			}
			if (this.password == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] passwordTmp = this.password.getBytes(StandardCharsets.UTF_8);
				output.writeInt(passwordTmp.length);
				output.write(passwordTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetPassportElement setPassportElement = (SetPassportElement) o;
			if (!Objects.equals(this.element, setPassportElement.element)) {
				return false;
			}
			if (this.password != setPassportElement.password) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.element == null ? 0 : this.element.hashCode();
			result = result * 31 + (this.password == null ? 0 : this.password.hashCode());
			return result;
		}
	}

	/**
	 * Informs the user that some of the elements in their Telegram Passport
	 * contain errors; for bots only. The user will not be able to resend
	 * the elements, until the errors are fixed.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetPassportElementErrors extends Function<Ok> {


		/**
		 * User identifier.
		**/
		public long userId;

		/**
		 * The errors.
		**/
		public InputPassportElementError[] errors;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2056754881;

		/**
		 * Informs the user that some of the elements in their Telegram Passport contain errors; for bots only. The user will not be able to resend the elements, until the errors are fixed.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetPassportElementErrors() {}

		/**
		 * Informs the user that some of the elements in their Telegram Passport contain errors; for bots only. The user will not be able to resend the elements, until the errors are fixed.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param userId User identifier.
		 * @param errors The errors.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetPassportElementErrors(long userId, InputPassportElementError[] errors) {
			this.userId = userId;
			this.errors = errors;
		}

		/**
		 * Informs the user that some of the elements in their Telegram Passport contain errors; for bots only. The user will not be able to resend the elements, until the errors are fixed.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetPassportElementErrors(DataInput input) throws IOException {
			this.userId = input.readLong();
			if (input.readBoolean()) {
				this.errors = new InputPassportElementError[input.readInt()];
				for (int i = 0; i < this.errors.length; i++) {
					if (InputPassportElementError.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.errors[i] = new InputPassportElementError(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetPassportElementErrors.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetPassportElementErrors.CONSTRUCTOR);
			output.writeLong(this.userId);
			if (this.errors == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.errors.length);
				for (int i = 0; i < this.errors.length; i++) {
					this.errors[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetPassportElementErrors setPassportElementErrors = (SetPassportElementErrors) o;
			if (this.userId != setPassportElementErrors.userId) {
				return false;
			}
			if (!Arrays.equals(this.errors, setPassportElementErrors.errors)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.userId);
			result = result * 31 + (Arrays.hashCode(this.errors));
			return result;
		}
	}

	/**
	 * Changes the 2-step verification password for the current user. If a
	 * new recovery email address is specified, then the change will not be
	 * applied until the new recovery email address is confirmed.
	 * <p> Returns {@link PasswordState PasswordState} </p>
	**/
	public static final class SetPassword extends Function<PasswordState> {


		/**
		 * Previous 2-step verification password of the user.
		**/
		public String oldPassword;

		/**
		 * New 2-step verification password of the user; may be empty to remove the password.
		**/
		public String newPassword;

		/**
		 * New password hint; may be empty.
		**/
		public String newHint;

		/**
		 * Pass true to change also the recovery email address.
		**/
		public boolean setRecoveryEmailAddress;

		/**
		 * New recovery email address; may be empty.
		**/
		public String newRecoveryEmailAddress;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1193589027;

		/**
		 * Changes the 2-step verification password for the current user. If a new recovery email address is specified, then the change will not be applied until the new recovery email address is confirmed.
		 *
		 * <p> Returns {@link PasswordState PasswordState} </p>
		**/
		public SetPassword() {}

		/**
		 * Changes the 2-step verification password for the current user. If a new recovery email address is specified, then the change will not be applied until the new recovery email address is confirmed.
		 *
		 * <p> Returns {@link PasswordState PasswordState} </p>
		 *
		 * @param oldPassword Previous 2-step verification password of the user.
		 * @param newPassword New 2-step verification password of the user; may be empty to remove the password.
		 * @param newHint New password hint; may be empty.
		 * @param setRecoveryEmailAddress Pass true to change also the recovery email address.
		 * @param newRecoveryEmailAddress New recovery email address; may be empty.
		 *
		 * <p> Returns {@link PasswordState PasswordState} </p>
		**/
		public SetPassword(String oldPassword,
				String newPassword,
				String newHint,
				boolean setRecoveryEmailAddress,
				String newRecoveryEmailAddress) {
			this.oldPassword = oldPassword;
			this.newPassword = newPassword;
			this.newHint = newHint;
			this.setRecoveryEmailAddress = setRecoveryEmailAddress;
			this.newRecoveryEmailAddress = newRecoveryEmailAddress;
		}

		/**
		 * Changes the 2-step verification password for the current user. If a new recovery email address is specified, then the change will not be applied until the new recovery email address is confirmed.
		 *
		 * <p> Returns {@link PasswordState PasswordState} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetPassword(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] oldPasswordTmp = new byte[input.readInt()];
				input.readFully(oldPasswordTmp);
				this.oldPassword = new String(oldPasswordTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] newPasswordTmp = new byte[input.readInt()];
				input.readFully(newPasswordTmp);
				this.newPassword = new String(newPasswordTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] newHintTmp = new byte[input.readInt()];
				input.readFully(newHintTmp);
				this.newHint = new String(newHintTmp, StandardCharsets.UTF_8);
			}
			this.setRecoveryEmailAddress = input.readBoolean();
			if (input.readBoolean()) {
				byte[] newRecoveryEmailAddressTmp = new byte[input.readInt()];
				input.readFully(newRecoveryEmailAddressTmp);
				this.newRecoveryEmailAddress = new String(newRecoveryEmailAddressTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetPassword.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetPassword.CONSTRUCTOR);
			if (this.oldPassword == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] oldPasswordTmp = this.oldPassword.getBytes(StandardCharsets.UTF_8);
				output.writeInt(oldPasswordTmp.length);
				output.write(oldPasswordTmp);
			}
			if (this.newPassword == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] newPasswordTmp = this.newPassword.getBytes(StandardCharsets.UTF_8);
				output.writeInt(newPasswordTmp.length);
				output.write(newPasswordTmp);
			}
			if (this.newHint == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] newHintTmp = this.newHint.getBytes(StandardCharsets.UTF_8);
				output.writeInt(newHintTmp.length);
				output.write(newHintTmp);
			}
			output.writeBoolean(this.setRecoveryEmailAddress);
			if (this.newRecoveryEmailAddress == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] newRecoveryEmailAddressTmp = this.newRecoveryEmailAddress.getBytes(StandardCharsets.UTF_8);
				output.writeInt(newRecoveryEmailAddressTmp.length);
				output.write(newRecoveryEmailAddressTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetPassword setPassword = (SetPassword) o;
			if (this.oldPassword != setPassword.oldPassword) {
				return false;
			}
			if (this.newPassword != setPassword.newPassword) {
				return false;
			}
			if (this.newHint != setPassword.newHint) {
				return false;
			}
			if (this.setRecoveryEmailAddress != setPassword.setRecoveryEmailAddress) {
				return false;
			}
			if (this.newRecoveryEmailAddress != setPassword.newRecoveryEmailAddress) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.setRecoveryEmailAddress);
			result = result * 31 + (this.oldPassword == null ? 0 : this.oldPassword.hashCode());
			result = result * 31 + (this.newPassword == null ? 0 : this.newPassword.hashCode());
			result = result * 31 + (this.newHint == null ? 0 : this.newHint.hashCode());
			result = result * 31 + (this.newRecoveryEmailAddress == null ? 0 : this.newRecoveryEmailAddress.hashCode());
			return result;
		}
	}

	/**
	 * Changes the order of pinned chats.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetPinnedChats extends Function<Ok> {


		/**
		 * Chat list in which to change the order of pinned chats.
		**/
		public ChatList chatList;

		/**
		 * The new list of pinned chats.
		**/
		public long[] chatIds;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -695640000;

		/**
		 * Changes the order of pinned chats.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetPinnedChats() {}

		/**
		 * Changes the order of pinned chats.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatList Chat list in which to change the order of pinned chats.
		 * @param chatIds The new list of pinned chats.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetPinnedChats(ChatList chatList, long[] chatIds) {
			this.chatList = chatList;
			this.chatIds = chatIds;
		}

		/**
		 * Changes the order of pinned chats.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetPinnedChats(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ChatListMain.CONSTRUCTOR: this.chatList = new ChatListMain(input); break;
					case ChatListArchive.CONSTRUCTOR: this.chatList = new ChatListArchive(input); break;
					case ChatListFolder.CONSTRUCTOR: this.chatList = new ChatListFolder(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				this.chatIds = new long[input.readInt()];
				for (int i = 0; i < this.chatIds.length; i++) {
					this.chatIds[i] = input.readLong();
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetPinnedChats.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetPinnedChats.CONSTRUCTOR);
			if (this.chatList == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.chatList.serialize(output);
			}
			if (this.chatIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.chatIds.length);
				for (int i = 0; i < this.chatIds.length; i++) {
					output.writeLong(this.chatIds[i]);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetPinnedChats setPinnedChats = (SetPinnedChats) o;
			if (!Objects.equals(this.chatList, setPinnedChats.chatList)) {
				return false;
			}
			if (!Arrays.equals(this.chatIds, setPinnedChats.chatIds)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.chatList == null ? 0 : this.chatList.hashCode();
			result = result * 31 + (Arrays.hashCode(this.chatIds));
			return result;
		}
	}

	/**
	 * Changes the order of pinned forum topics.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetPinnedForumTopics extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * The new list of pinned forum topics.
		**/
		public long[] messageThreadIds;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -475084011;

		/**
		 * Changes the order of pinned forum topics.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetPinnedForumTopics() {}

		/**
		 * Changes the order of pinned forum topics.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param messageThreadIds The new list of pinned forum topics.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetPinnedForumTopics(long chatId, long[] messageThreadIds) {
			this.chatId = chatId;
			this.messageThreadIds = messageThreadIds;
		}

		/**
		 * Changes the order of pinned forum topics.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetPinnedForumTopics(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				this.messageThreadIds = new long[input.readInt()];
				for (int i = 0; i < this.messageThreadIds.length; i++) {
					this.messageThreadIds[i] = input.readLong();
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetPinnedForumTopics.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetPinnedForumTopics.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.messageThreadIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.messageThreadIds.length);
				for (int i = 0; i < this.messageThreadIds.length; i++) {
					output.writeLong(this.messageThreadIds[i]);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetPinnedForumTopics setPinnedForumTopics = (SetPinnedForumTopics) o;
			if (this.chatId != setPinnedForumTopics.chatId) {
				return false;
			}
			if (!Arrays.equals(this.messageThreadIds, setPinnedForumTopics.messageThreadIds)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (Arrays.hashCode(this.messageThreadIds));
			return result;
		}
	}

	/**
	 * Changes the user answer to a poll. A poll in quiz mode can be
	 * answered only once.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetPollAnswer extends Function<Ok> {


		/**
		 * Identifier of the chat to which the poll belongs.
		**/
		public long chatId;

		/**
		 * Identifier of the message containing the poll.
		**/
		public long messageId;

		/**
		 * 0-based identifiers of answer options, chosen by the user. User can choose more than 1 answer option only is the poll allows multiple answers.
		**/
		public int[] optionIds;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1399388792;

		/**
		 * Changes the user answer to a poll. A poll in quiz mode can be answered only once.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetPollAnswer() {}

		/**
		 * Changes the user answer to a poll. A poll in quiz mode can be answered only once.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Identifier of the chat to which the poll belongs.
		 * @param messageId Identifier of the message containing the poll.
		 * @param optionIds 0-based identifiers of answer options, chosen by the user. User can choose more than 1 answer option only is the poll allows multiple answers.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetPollAnswer(long chatId, long messageId, int[] optionIds) {
			this.chatId = chatId;
			this.messageId = messageId;
			this.optionIds = optionIds;
		}

		/**
		 * Changes the user answer to a poll. A poll in quiz mode can be answered only once.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetPollAnswer(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
			if (input.readBoolean()) {
				this.optionIds = new int[input.readInt()];
				for (int i = 0; i < this.optionIds.length; i++) {
					this.optionIds[i] = input.readInt();
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetPollAnswer.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetPollAnswer.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
			if (this.optionIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.optionIds.length);
				for (int i = 0; i < this.optionIds.length; i++) {
					output.writeInt(this.optionIds[i]);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetPollAnswer setPollAnswer = (SetPollAnswer) o;
			if (this.chatId != setPollAnswer.chatId) {
				return false;
			}
			if (this.messageId != setPollAnswer.messageId) {
				return false;
			}
			if (!Arrays.equals(this.optionIds, setPollAnswer.optionIds)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (Arrays.hashCode(this.optionIds));
			return result;
		}
	}

	/**
	 * Changes a profile photo for the current user.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetProfilePhoto extends Function<Ok> {


		/**
		 * Profile photo to set.
		**/
		public InputChatPhoto photo;

		/**
		 * Pass true to set a public photo, which will be visible even the main photo is hidden by privacy settings.
		**/
		public boolean isPublic;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2048260627;

		/**
		 * Changes a profile photo for the current user.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetProfilePhoto() {}

		/**
		 * Changes a profile photo for the current user.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param photo Profile photo to set.
		 * @param isPublic Pass true to set a public photo, which will be visible even the main photo is hidden by privacy settings.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetProfilePhoto(InputChatPhoto photo, boolean isPublic) {
			this.photo = photo;
			this.isPublic = isPublic;
		}

		/**
		 * Changes a profile photo for the current user.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetProfilePhoto(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputChatPhotoPrevious.CONSTRUCTOR: this.photo = new InputChatPhotoPrevious(input); break;
					case InputChatPhotoStatic.CONSTRUCTOR: this.photo = new InputChatPhotoStatic(input); break;
					case InputChatPhotoAnimation.CONSTRUCTOR: this.photo = new InputChatPhotoAnimation(input); break;
					case InputChatPhotoSticker.CONSTRUCTOR: this.photo = new InputChatPhotoSticker(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.isPublic = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetProfilePhoto.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetProfilePhoto.CONSTRUCTOR);
			if (this.photo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.photo.serialize(output);
			}
			output.writeBoolean(this.isPublic);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetProfilePhoto setProfilePhoto = (SetProfilePhoto) o;
			if (!Objects.equals(this.photo, setProfilePhoto.photo)) {
				return false;
			}
			if (this.isPublic != setProfilePhoto.isPublic) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isPublic);
			result = result * 31 + (this.photo == null ? 0 : this.photo.hashCode());
			return result;
		}
	}

	/**
	 * Changes the 2-step verification recovery email address of the user.
	 * If a new recovery email address is specified, then the change will
	 * not be applied until the new recovery email address is confirmed. If
	 * newRecoveryEmailAddress is the same as the email address that is
	 * currently set up, this call succeeds immediately and aborts all other
	 * requests waiting for an email confirmation.
	 * <p> Returns {@link PasswordState PasswordState} </p>
	**/
	public static final class SetRecoveryEmailAddress extends Function<PasswordState> {


		/**
		 * The 2-step verification password of the current user.
		**/
		public String password;

		/**
		 * New recovery email address.
		**/
		public String newRecoveryEmailAddress;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1981836385;

		/**
		 * Changes the 2-step verification recovery email address of the user. If a new recovery email address is specified, then the change will not be applied until the new recovery email address is confirmed. If newRecoveryEmailAddress is the same as the email address that is currently set up, this call succeeds immediately and aborts all other requests waiting for an email confirmation.
		 *
		 * <p> Returns {@link PasswordState PasswordState} </p>
		**/
		public SetRecoveryEmailAddress() {}

		/**
		 * Changes the 2-step verification recovery email address of the user. If a new recovery email address is specified, then the change will not be applied until the new recovery email address is confirmed. If newRecoveryEmailAddress is the same as the email address that is currently set up, this call succeeds immediately and aborts all other requests waiting for an email confirmation.
		 *
		 * <p> Returns {@link PasswordState PasswordState} </p>
		 *
		 * @param password The 2-step verification password of the current user.
		 * @param newRecoveryEmailAddress New recovery email address.
		 *
		 * <p> Returns {@link PasswordState PasswordState} </p>
		**/
		public SetRecoveryEmailAddress(String password, String newRecoveryEmailAddress) {
			this.password = password;
			this.newRecoveryEmailAddress = newRecoveryEmailAddress;
		}

		/**
		 * Changes the 2-step verification recovery email address of the user. If a new recovery email address is specified, then the change will not be applied until the new recovery email address is confirmed. If newRecoveryEmailAddress is the same as the email address that is currently set up, this call succeeds immediately and aborts all other requests waiting for an email confirmation.
		 *
		 * <p> Returns {@link PasswordState PasswordState} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetRecoveryEmailAddress(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] passwordTmp = new byte[input.readInt()];
				input.readFully(passwordTmp);
				this.password = new String(passwordTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] newRecoveryEmailAddressTmp = new byte[input.readInt()];
				input.readFully(newRecoveryEmailAddressTmp);
				this.newRecoveryEmailAddress = new String(newRecoveryEmailAddressTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetRecoveryEmailAddress.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetRecoveryEmailAddress.CONSTRUCTOR);
			if (this.password == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] passwordTmp = this.password.getBytes(StandardCharsets.UTF_8);
				output.writeInt(passwordTmp.length);
				output.write(passwordTmp);
			}
			if (this.newRecoveryEmailAddress == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] newRecoveryEmailAddressTmp = this.newRecoveryEmailAddress.getBytes(StandardCharsets.UTF_8);
				output.writeInt(newRecoveryEmailAddressTmp.length);
				output.write(newRecoveryEmailAddressTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetRecoveryEmailAddress setRecoveryEmailAddress = (SetRecoveryEmailAddress) o;
			if (this.password != setRecoveryEmailAddress.password) {
				return false;
			}
			if (this.newRecoveryEmailAddress != setRecoveryEmailAddress.newRecoveryEmailAddress) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.password == null ? 0 : this.password.hashCode();
			result = result * 31 + (this.newRecoveryEmailAddress == null ? 0 : this.newRecoveryEmailAddress.hashCode());
			return result;
		}
	}

	/**
	 * Changes notification settings for chats of a given type.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetScopeNotificationSettings extends Function<Ok> {


		/**
		 * Types of chats for which to change the notification settings.
		**/
		public NotificationSettingsScope scope;

		/**
		 * The new notification settings for the given scope.
		**/
		public ScopeNotificationSettings notificationSettings;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2049984966;

		/**
		 * Changes notification settings for chats of a given type.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetScopeNotificationSettings() {}

		/**
		 * Changes notification settings for chats of a given type.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param scope Types of chats for which to change the notification settings.
		 * @param notificationSettings The new notification settings for the given scope.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetScopeNotificationSettings(NotificationSettingsScope scope,
				ScopeNotificationSettings notificationSettings) {
			this.scope = scope;
			this.notificationSettings = notificationSettings;
		}

		/**
		 * Changes notification settings for chats of a given type.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetScopeNotificationSettings(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case NotificationSettingsScopePrivateChats.CONSTRUCTOR: this.scope = new NotificationSettingsScopePrivateChats(input); break;
					case NotificationSettingsScopeGroupChats.CONSTRUCTOR: this.scope = new NotificationSettingsScopeGroupChats(input); break;
					case NotificationSettingsScopeChannelChats.CONSTRUCTOR: this.scope = new NotificationSettingsScopeChannelChats(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				if (ScopeNotificationSettings.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.notificationSettings = new ScopeNotificationSettings(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetScopeNotificationSettings.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetScopeNotificationSettings.CONSTRUCTOR);
			if (this.scope == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.scope.serialize(output);
			}
			if (this.notificationSettings == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.notificationSettings.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetScopeNotificationSettings setScopeNotificationSettings = (SetScopeNotificationSettings) o;
			if (!Objects.equals(this.scope, setScopeNotificationSettings.scope)) {
				return false;
			}
			if (!Objects.equals(this.notificationSettings, setScopeNotificationSettings.notificationSettings)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.scope == null ? 0 : this.scope.hashCode();
			result = result * 31 + (this.notificationSettings == null ? 0 : this.notificationSettings.hashCode());
			return result;
		}
	}

	/**
	 * Changes the list of emoji corresponding to a sticker; for bots only.
	 * The sticker must belong to a regular or custom emoji sticker set
	 * created by the bot.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetStickerEmojis extends Function<Ok> {


		/**
		 * Sticker.
		**/
		public InputFile sticker;

		/**
		 * New string with 1-20 emoji corresponding to the sticker.
		**/
		public String emojis;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -638843855;

		/**
		 * Changes the list of emoji corresponding to a sticker; for bots only. The sticker must belong to a regular or custom emoji sticker set created by the bot.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetStickerEmojis() {}

		/**
		 * Changes the list of emoji corresponding to a sticker; for bots only. The sticker must belong to a regular or custom emoji sticker set created by the bot.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param sticker Sticker.
		 * @param emojis New string with 1-20 emoji corresponding to the sticker.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetStickerEmojis(InputFile sticker, String emojis) {
			this.sticker = sticker;
			this.emojis = emojis;
		}

		/**
		 * Changes the list of emoji corresponding to a sticker; for bots only. The sticker must belong to a regular or custom emoji sticker set created by the bot.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetStickerEmojis(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputFileId.CONSTRUCTOR: this.sticker = new InputFileId(input); break;
					case InputFileRemote.CONSTRUCTOR: this.sticker = new InputFileRemote(input); break;
					case InputFileLocal.CONSTRUCTOR: this.sticker = new InputFileLocal(input); break;
					case InputFileGenerated.CONSTRUCTOR: this.sticker = new InputFileGenerated(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				byte[] emojisTmp = new byte[input.readInt()];
				input.readFully(emojisTmp);
				this.emojis = new String(emojisTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetStickerEmojis.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetStickerEmojis.CONSTRUCTOR);
			if (this.sticker == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.sticker.serialize(output);
			}
			if (this.emojis == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] emojisTmp = this.emojis.getBytes(StandardCharsets.UTF_8);
				output.writeInt(emojisTmp.length);
				output.write(emojisTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetStickerEmojis setStickerEmojis = (SetStickerEmojis) o;
			if (!Objects.equals(this.sticker, setStickerEmojis.sticker)) {
				return false;
			}
			if (this.emojis != setStickerEmojis.emojis) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.sticker == null ? 0 : this.sticker.hashCode();
			result = result * 31 + (this.emojis == null ? 0 : this.emojis.hashCode());
			return result;
		}
	}

	/**
	 * Changes the list of keywords of a sticker; for bots only. The sticker
	 * must belong to a regular or custom emoji sticker set created by the
	 * bot.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetStickerKeywords extends Function<Ok> {


		/**
		 * Sticker.
		**/
		public InputFile sticker;

		/**
		 * List of up to 20 keywords with total length up to 64 characters, which can be used to find the sticker.
		**/
		public String[] keywords;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 137223565;

		/**
		 * Changes the list of keywords of a sticker; for bots only. The sticker must belong to a regular or custom emoji sticker set created by the bot.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetStickerKeywords() {}

		/**
		 * Changes the list of keywords of a sticker; for bots only. The sticker must belong to a regular or custom emoji sticker set created by the bot.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param sticker Sticker.
		 * @param keywords List of up to 20 keywords with total length up to 64 characters, which can be used to find the sticker.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetStickerKeywords(InputFile sticker, String[] keywords) {
			this.sticker = sticker;
			this.keywords = keywords;
		}

		/**
		 * Changes the list of keywords of a sticker; for bots only. The sticker must belong to a regular or custom emoji sticker set created by the bot.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetStickerKeywords(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputFileId.CONSTRUCTOR: this.sticker = new InputFileId(input); break;
					case InputFileRemote.CONSTRUCTOR: this.sticker = new InputFileRemote(input); break;
					case InputFileLocal.CONSTRUCTOR: this.sticker = new InputFileLocal(input); break;
					case InputFileGenerated.CONSTRUCTOR: this.sticker = new InputFileGenerated(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				this.keywords = new String[input.readInt()];
				for (int i = 0; i < this.keywords.length; i++) {
					byte[] keywordsTmp = new byte[input.readInt()];
					input.readFully(keywordsTmp);
					this.keywords[i] = new String(keywordsTmp, StandardCharsets.UTF_8);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetStickerKeywords.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetStickerKeywords.CONSTRUCTOR);
			if (this.sticker == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.sticker.serialize(output);
			}
			if (this.keywords == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.keywords.length);
				for (int i = 0; i < this.keywords.length; i++) {
					byte[] keywordsTmp = this.keywords[i].getBytes(StandardCharsets.UTF_8);
					output.writeInt(keywordsTmp.length);
					output.write(keywordsTmp);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetStickerKeywords setStickerKeywords = (SetStickerKeywords) o;
			if (!Objects.equals(this.sticker, setStickerKeywords.sticker)) {
				return false;
			}
			if (!Arrays.equals(this.keywords, setStickerKeywords.keywords)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.sticker == null ? 0 : this.sticker.hashCode();
			result = result * 31 + (Arrays.hashCode(this.keywords));
			return result;
		}
	}

	/**
	 * Changes the mask position of a mask sticker; for bots only. The
	 * sticker must belong to a mask sticker set created by the bot.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetStickerMaskPosition extends Function<Ok> {


		/**
		 * Sticker.
		**/
		public InputFile sticker;

		/**
		 * Position where the mask is placed; pass null to remove mask position.
		**/
		public MaskPosition maskPosition;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1202280912;

		/**
		 * Changes the mask position of a mask sticker; for bots only. The sticker must belong to a mask sticker set created by the bot.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetStickerMaskPosition() {}

		/**
		 * Changes the mask position of a mask sticker; for bots only. The sticker must belong to a mask sticker set created by the bot.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param sticker Sticker.
		 * @param maskPosition Position where the mask is placed; pass null to remove mask position.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetStickerMaskPosition(InputFile sticker, MaskPosition maskPosition) {
			this.sticker = sticker;
			this.maskPosition = maskPosition;
		}

		/**
		 * Changes the mask position of a mask sticker; for bots only. The sticker must belong to a mask sticker set created by the bot.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetStickerMaskPosition(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputFileId.CONSTRUCTOR: this.sticker = new InputFileId(input); break;
					case InputFileRemote.CONSTRUCTOR: this.sticker = new InputFileRemote(input); break;
					case InputFileLocal.CONSTRUCTOR: this.sticker = new InputFileLocal(input); break;
					case InputFileGenerated.CONSTRUCTOR: this.sticker = new InputFileGenerated(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				if (MaskPosition.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.maskPosition = new MaskPosition(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetStickerMaskPosition.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetStickerMaskPosition.CONSTRUCTOR);
			if (this.sticker == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.sticker.serialize(output);
			}
			if (this.maskPosition == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.maskPosition.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetStickerMaskPosition setStickerMaskPosition = (SetStickerMaskPosition) o;
			if (!Objects.equals(this.sticker, setStickerMaskPosition.sticker)) {
				return false;
			}
			if (!Objects.equals(this.maskPosition, setStickerMaskPosition.maskPosition)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.sticker == null ? 0 : this.sticker.hashCode();
			result = result * 31 + (this.maskPosition == null ? 0 : this.maskPosition.hashCode());
			return result;
		}
	}

	/**
	 * Changes the position of a sticker in the set to which it belongs; for
	 * bots only. The sticker set must have been created by the bot.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetStickerPositionInSet extends Function<Ok> {


		/**
		 * Sticker.
		**/
		public InputFile sticker;

		/**
		 * New position of the sticker in the set, 0-based.
		**/
		public int position;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2075281185;

		/**
		 * Changes the position of a sticker in the set to which it belongs; for bots only. The sticker set must have been created by the bot.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetStickerPositionInSet() {}

		/**
		 * Changes the position of a sticker in the set to which it belongs; for bots only. The sticker set must have been created by the bot.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param sticker Sticker.
		 * @param position New position of the sticker in the set, 0-based.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetStickerPositionInSet(InputFile sticker, int position) {
			this.sticker = sticker;
			this.position = position;
		}

		/**
		 * Changes the position of a sticker in the set to which it belongs; for bots only. The sticker set must have been created by the bot.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetStickerPositionInSet(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputFileId.CONSTRUCTOR: this.sticker = new InputFileId(input); break;
					case InputFileRemote.CONSTRUCTOR: this.sticker = new InputFileRemote(input); break;
					case InputFileLocal.CONSTRUCTOR: this.sticker = new InputFileLocal(input); break;
					case InputFileGenerated.CONSTRUCTOR: this.sticker = new InputFileGenerated(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.position = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetStickerPositionInSet.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetStickerPositionInSet.CONSTRUCTOR);
			if (this.sticker == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.sticker.serialize(output);
			}
			output.writeInt(this.position);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetStickerPositionInSet setStickerPositionInSet = (SetStickerPositionInSet) o;
			if (!Objects.equals(this.sticker, setStickerPositionInSet.sticker)) {
				return false;
			}
			if (this.position != setStickerPositionInSet.position) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.position);
			result = result * 31 + (this.sticker == null ? 0 : this.sticker.hashCode());
			return result;
		}
	}

	/**
	 * Sets a sticker set thumbnail; for bots only.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetStickerSetThumbnail extends Function<Ok> {


		/**
		 * Sticker set owner.
		**/
		public long userId;

		/**
		 * Sticker set name.
		**/
		public String name;

		/**
		 * Thumbnail to set in PNG, TGS, or WEBM format; pass null to remove the sticker set thumbnail. Thumbnail format must match the format of stickers in the set.
		**/
		public InputFile thumbnail;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1870737953;

		/**
		 * Sets a sticker set thumbnail; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetStickerSetThumbnail() {}

		/**
		 * Sets a sticker set thumbnail; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param userId Sticker set owner.
		 * @param name Sticker set name.
		 * @param thumbnail Thumbnail to set in PNG, TGS, or WEBM format; pass null to remove the sticker set thumbnail. Thumbnail format must match the format of stickers in the set.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetStickerSetThumbnail(long userId, String name, InputFile thumbnail) {
			this.userId = userId;
			this.name = name;
			this.thumbnail = thumbnail;
		}

		/**
		 * Sets a sticker set thumbnail; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetStickerSetThumbnail(DataInput input) throws IOException {
			this.userId = input.readLong();
			if (input.readBoolean()) {
				byte[] nameTmp = new byte[input.readInt()];
				input.readFully(nameTmp);
				this.name = new String(nameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputFileId.CONSTRUCTOR: this.thumbnail = new InputFileId(input); break;
					case InputFileRemote.CONSTRUCTOR: this.thumbnail = new InputFileRemote(input); break;
					case InputFileLocal.CONSTRUCTOR: this.thumbnail = new InputFileLocal(input); break;
					case InputFileGenerated.CONSTRUCTOR: this.thumbnail = new InputFileGenerated(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetStickerSetThumbnail.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetStickerSetThumbnail.CONSTRUCTOR);
			output.writeLong(this.userId);
			if (this.name == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nameTmp = this.name.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nameTmp.length);
				output.write(nameTmp);
			}
			if (this.thumbnail == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.thumbnail.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetStickerSetThumbnail setStickerSetThumbnail = (SetStickerSetThumbnail) o;
			if (this.userId != setStickerSetThumbnail.userId) {
				return false;
			}
			if (this.name != setStickerSetThumbnail.name) {
				return false;
			}
			if (!Objects.equals(this.thumbnail, setStickerSetThumbnail.thumbnail)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.userId);
			result = result * 31 + (this.name == null ? 0 : this.name.hashCode());
			result = result * 31 + (this.thumbnail == null ? 0 : this.thumbnail.hashCode());
			return result;
		}
	}

	/**
	 * Sets a sticker set title; for bots only.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetStickerSetTitle extends Function<Ok> {


		/**
		 * Sticker set name.
		**/
		public String name;

		/**
		 * New sticker set title.
		**/
		public String title;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1693004706;

		/**
		 * Sets a sticker set title; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetStickerSetTitle() {}

		/**
		 * Sets a sticker set title; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param name Sticker set name.
		 * @param title New sticker set title.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetStickerSetTitle(String name, String title) {
			this.name = name;
			this.title = title;
		}

		/**
		 * Sets a sticker set title; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetStickerSetTitle(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] nameTmp = new byte[input.readInt()];
				input.readFully(nameTmp);
				this.name = new String(nameTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetStickerSetTitle.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetStickerSetTitle.CONSTRUCTOR);
			if (this.name == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] nameTmp = this.name.getBytes(StandardCharsets.UTF_8);
				output.writeInt(nameTmp.length);
				output.write(nameTmp);
			}
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetStickerSetTitle setStickerSetTitle = (SetStickerSetTitle) o;
			if (this.name != setStickerSetTitle.name) {
				return false;
			}
			if (this.title != setStickerSetTitle.title) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.name == null ? 0 : this.name.hashCode();
			result = result * 31 + (this.title == null ? 0 : this.title.hashCode());
			return result;
		}
	}

	/**
	 * Changes the sticker set of a supergroup; requires canChangeInfo
	 * administrator right.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetSupergroupStickerSet extends Function<Ok> {


		/**
		 * Identifier of the supergroup.
		**/
		public long supergroupId;

		/**
		 * New value of the supergroup sticker set identifier. Use 0 to remove the supergroup sticker set.
		**/
		public long stickerSetId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2056344215;

		/**
		 * Changes the sticker set of a supergroup; requires canChangeInfo administrator right.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetSupergroupStickerSet() {}

		/**
		 * Changes the sticker set of a supergroup; requires canChangeInfo administrator right.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param supergroupId Identifier of the supergroup.
		 * @param stickerSetId New value of the supergroup sticker set identifier. Use 0 to remove the supergroup sticker set.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetSupergroupStickerSet(long supergroupId, long stickerSetId) {
			this.supergroupId = supergroupId;
			this.stickerSetId = stickerSetId;
		}

		/**
		 * Changes the sticker set of a supergroup; requires canChangeInfo administrator right.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetSupergroupStickerSet(DataInput input) throws IOException {
			this.supergroupId = input.readLong();
			this.stickerSetId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetSupergroupStickerSet.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetSupergroupStickerSet.CONSTRUCTOR);
			output.writeLong(this.supergroupId);
			output.writeLong(this.stickerSetId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetSupergroupStickerSet setSupergroupStickerSet = (SetSupergroupStickerSet) o;
			if (this.supergroupId != setSupergroupStickerSet.supergroupId) {
				return false;
			}
			if (this.stickerSetId != setSupergroupStickerSet.stickerSetId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.supergroupId);
			return result;
		}
	}

	/**
	 * Changes the editable username of a supergroup or channel, requires
	 * owner privileges in the supergroup or channel.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetSupergroupUsername extends Function<Ok> {


		/**
		 * Identifier of the supergroup or channel.
		**/
		public long supergroupId;

		/**
		 * New value of the username. Use an empty string to remove the username. The username can&#039;t be completely removed if there is another active or disabled username.
		**/
		public String username;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1346325252;

		/**
		 * Changes the editable username of a supergroup or channel, requires owner privileges in the supergroup or channel.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetSupergroupUsername() {}

		/**
		 * Changes the editable username of a supergroup or channel, requires owner privileges in the supergroup or channel.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param supergroupId Identifier of the supergroup or channel.
		 * @param username New value of the username. Use an empty string to remove the username. The username can&#039;t be completely removed if there is another active or disabled username.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetSupergroupUsername(long supergroupId, String username) {
			this.supergroupId = supergroupId;
			this.username = username;
		}

		/**
		 * Changes the editable username of a supergroup or channel, requires owner privileges in the supergroup or channel.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetSupergroupUsername(DataInput input) throws IOException {
			this.supergroupId = input.readLong();
			if (input.readBoolean()) {
				byte[] usernameTmp = new byte[input.readInt()];
				input.readFully(usernameTmp);
				this.username = new String(usernameTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetSupergroupUsername.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetSupergroupUsername.CONSTRUCTOR);
			output.writeLong(this.supergroupId);
			if (this.username == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] usernameTmp = this.username.getBytes(StandardCharsets.UTF_8);
				output.writeInt(usernameTmp.length);
				output.write(usernameTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetSupergroupUsername setSupergroupUsername = (SetSupergroupUsername) o;
			if (this.supergroupId != setSupergroupUsername.supergroupId) {
				return false;
			}
			if (this.username != setSupergroupUsername.username) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.supergroupId);
			result = result * 31 + (this.username == null ? 0 : this.username.hashCode());
			return result;
		}
	}

	/**
	 * Sets the parameters for TDLib initialization. Works only when the
	 * current authorization state is authorizationStateWaitTdlibParameters.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetTdlibParameters extends Function<Ok> {


		/**
		 * Pass true to use Telegram test environment instead of the production environment.
		**/
		public boolean useTestDc;

		/**
		 * The path to the directory for the persistent database; if empty, the current working directory will be used.
		**/
		public String databaseDirectory;

		/**
		 * The path to the directory for storing files; if empty, databaseDirectory will be used.
		**/
		public String filesDirectory;

		/**
		 * Encryption key for the database. If the encryption key is invalid, then an error with code 401 will be returned.
		**/
		public byte[] databaseEncryptionKey;

		/**
		 * Pass true to keep information about downloaded and uploaded files between application restarts.
		**/
		public boolean useFileDatabase;

		/**
		 * Pass true to keep cache of users, basic groups, supergroups, channels and secret chats between restarts. Implies useFileDatabase.
		**/
		public boolean useChatInfoDatabase;

		/**
		 * Pass true to keep cache of chats and messages between restarts. Implies useChatInfoDatabase.
		**/
		public boolean useMessageDatabase;

		/**
		 * Pass true to enable support for secret chats.
		**/
		public boolean useSecretChats;

		/**
		 * Application identifier for Telegram API access, which can be obtained at https://my.telegram.org.
		**/
		public int apiId;

		/**
		 * Application identifier hash for Telegram API access, which can be obtained at https://my.telegram.org.
		**/
		public String apiHash;

		/**
		 * IETF language tag of the user&#039;s operating system language; must be non-empty.
		**/
		public String systemLanguageCode;

		/**
		 * Model of the device the application is being run on; must be non-empty.
		**/
		public String deviceModel;

		/**
		 * Version of the operating system the application is being run on. If empty, the version is automatically detected by TDLib.
		**/
		public String systemVersion;

		/**
		 * Application version; must be non-empty.
		**/
		public String applicationVersion;

		/**
		 * Pass true to automatically delete old files in background.
		**/
		public boolean enableStorageOptimizer;

		/**
		 * Pass true to ignore original file names for downloaded files. Otherwise, downloaded files are saved under names as close as possible to the original name.
		**/
		public boolean ignoreFileNames;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1384743481;

		/**
		 * Sets the parameters for TDLib initialization. Works only when the current authorization state is authorizationStateWaitTdlibParameters.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetTdlibParameters() {}

		/**
		 * Sets the parameters for TDLib initialization. Works only when the current authorization state is authorizationStateWaitTdlibParameters.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param useTestDc Pass true to use Telegram test environment instead of the production environment.
		 * @param databaseDirectory The path to the directory for the persistent database; if empty, the current working directory will be used.
		 * @param filesDirectory The path to the directory for storing files; if empty, databaseDirectory will be used.
		 * @param databaseEncryptionKey Encryption key for the database. If the encryption key is invalid, then an error with code 401 will be returned.
		 * @param useFileDatabase Pass true to keep information about downloaded and uploaded files between application restarts.
		 * @param useChatInfoDatabase Pass true to keep cache of users, basic groups, supergroups, channels and secret chats between restarts. Implies useFileDatabase.
		 * @param useMessageDatabase Pass true to keep cache of chats and messages between restarts. Implies useChatInfoDatabase.
		 * @param useSecretChats Pass true to enable support for secret chats.
		 * @param apiId Application identifier for Telegram API access, which can be obtained at https://my.telegram.org.
		 * @param apiHash Application identifier hash for Telegram API access, which can be obtained at https://my.telegram.org.
		 * @param systemLanguageCode IETF language tag of the user&#039;s operating system language; must be non-empty.
		 * @param deviceModel Model of the device the application is being run on; must be non-empty.
		 * @param systemVersion Version of the operating system the application is being run on. If empty, the version is automatically detected by TDLib.
		 * @param applicationVersion Application version; must be non-empty.
		 * @param enableStorageOptimizer Pass true to automatically delete old files in background.
		 * @param ignoreFileNames Pass true to ignore original file names for downloaded files. Otherwise, downloaded files are saved under names as close as possible to the original name.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetTdlibParameters(boolean useTestDc,
				String databaseDirectory,
				String filesDirectory,
				byte[] databaseEncryptionKey,
				boolean useFileDatabase,
				boolean useChatInfoDatabase,
				boolean useMessageDatabase,
				boolean useSecretChats,
				int apiId,
				String apiHash,
				String systemLanguageCode,
				String deviceModel,
				String systemVersion,
				String applicationVersion,
				boolean enableStorageOptimizer,
				boolean ignoreFileNames) {
			this.useTestDc = useTestDc;
			this.databaseDirectory = databaseDirectory;
			this.filesDirectory = filesDirectory;
			this.databaseEncryptionKey = databaseEncryptionKey;
			this.useFileDatabase = useFileDatabase;
			this.useChatInfoDatabase = useChatInfoDatabase;
			this.useMessageDatabase = useMessageDatabase;
			this.useSecretChats = useSecretChats;
			this.apiId = apiId;
			this.apiHash = apiHash;
			this.systemLanguageCode = systemLanguageCode;
			this.deviceModel = deviceModel;
			this.systemVersion = systemVersion;
			this.applicationVersion = applicationVersion;
			this.enableStorageOptimizer = enableStorageOptimizer;
			this.ignoreFileNames = ignoreFileNames;
		}

		/**
		 * Sets the parameters for TDLib initialization. Works only when the current authorization state is authorizationStateWaitTdlibParameters.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetTdlibParameters(DataInput input) throws IOException {
			this.useTestDc = input.readBoolean();
			if (input.readBoolean()) {
				byte[] databaseDirectoryTmp = new byte[input.readInt()];
				input.readFully(databaseDirectoryTmp);
				this.databaseDirectory = new String(databaseDirectoryTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] filesDirectoryTmp = new byte[input.readInt()];
				input.readFully(filesDirectoryTmp);
				this.filesDirectory = new String(filesDirectoryTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				this.databaseEncryptionKey = new byte[input.readInt()];
				input.readFully(this.databaseEncryptionKey);
			}
			this.useFileDatabase = input.readBoolean();
			this.useChatInfoDatabase = input.readBoolean();
			this.useMessageDatabase = input.readBoolean();
			this.useSecretChats = input.readBoolean();
			this.apiId = input.readInt();
			if (input.readBoolean()) {
				byte[] apiHashTmp = new byte[input.readInt()];
				input.readFully(apiHashTmp);
				this.apiHash = new String(apiHashTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] systemLanguageCodeTmp = new byte[input.readInt()];
				input.readFully(systemLanguageCodeTmp);
				this.systemLanguageCode = new String(systemLanguageCodeTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] deviceModelTmp = new byte[input.readInt()];
				input.readFully(deviceModelTmp);
				this.deviceModel = new String(deviceModelTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] systemVersionTmp = new byte[input.readInt()];
				input.readFully(systemVersionTmp);
				this.systemVersion = new String(systemVersionTmp, StandardCharsets.UTF_8);
			}
			if (input.readBoolean()) {
				byte[] applicationVersionTmp = new byte[input.readInt()];
				input.readFully(applicationVersionTmp);
				this.applicationVersion = new String(applicationVersionTmp, StandardCharsets.UTF_8);
			}
			this.enableStorageOptimizer = input.readBoolean();
			this.ignoreFileNames = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetTdlibParameters.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetTdlibParameters.CONSTRUCTOR);
			output.writeBoolean(this.useTestDc);
			if (this.databaseDirectory == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] databaseDirectoryTmp = this.databaseDirectory.getBytes(StandardCharsets.UTF_8);
				output.writeInt(databaseDirectoryTmp.length);
				output.write(databaseDirectoryTmp);
			}
			if (this.filesDirectory == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] filesDirectoryTmp = this.filesDirectory.getBytes(StandardCharsets.UTF_8);
				output.writeInt(filesDirectoryTmp.length);
				output.write(filesDirectoryTmp);
			}
			if (this.databaseEncryptionKey == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.databaseEncryptionKey.length);
				output.write(this.databaseEncryptionKey);
			}
			output.writeBoolean(this.useFileDatabase);
			output.writeBoolean(this.useChatInfoDatabase);
			output.writeBoolean(this.useMessageDatabase);
			output.writeBoolean(this.useSecretChats);
			output.writeInt(this.apiId);
			if (this.apiHash == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] apiHashTmp = this.apiHash.getBytes(StandardCharsets.UTF_8);
				output.writeInt(apiHashTmp.length);
				output.write(apiHashTmp);
			}
			if (this.systemLanguageCode == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] systemLanguageCodeTmp = this.systemLanguageCode.getBytes(StandardCharsets.UTF_8);
				output.writeInt(systemLanguageCodeTmp.length);
				output.write(systemLanguageCodeTmp);
			}
			if (this.deviceModel == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] deviceModelTmp = this.deviceModel.getBytes(StandardCharsets.UTF_8);
				output.writeInt(deviceModelTmp.length);
				output.write(deviceModelTmp);
			}
			if (this.systemVersion == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] systemVersionTmp = this.systemVersion.getBytes(StandardCharsets.UTF_8);
				output.writeInt(systemVersionTmp.length);
				output.write(systemVersionTmp);
			}
			if (this.applicationVersion == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] applicationVersionTmp = this.applicationVersion.getBytes(StandardCharsets.UTF_8);
				output.writeInt(applicationVersionTmp.length);
				output.write(applicationVersionTmp);
			}
			output.writeBoolean(this.enableStorageOptimizer);
			output.writeBoolean(this.ignoreFileNames);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetTdlibParameters setTdlibParameters = (SetTdlibParameters) o;
			if (this.useTestDc != setTdlibParameters.useTestDc) {
				return false;
			}
			if (this.databaseDirectory != setTdlibParameters.databaseDirectory) {
				return false;
			}
			if (this.filesDirectory != setTdlibParameters.filesDirectory) {
				return false;
			}
			if (this.databaseEncryptionKey != setTdlibParameters.databaseEncryptionKey) {
				return false;
			}
			if (this.useFileDatabase != setTdlibParameters.useFileDatabase) {
				return false;
			}
			if (this.useChatInfoDatabase != setTdlibParameters.useChatInfoDatabase) {
				return false;
			}
			if (this.useMessageDatabase != setTdlibParameters.useMessageDatabase) {
				return false;
			}
			if (this.useSecretChats != setTdlibParameters.useSecretChats) {
				return false;
			}
			if (this.apiId != setTdlibParameters.apiId) {
				return false;
			}
			if (this.apiHash != setTdlibParameters.apiHash) {
				return false;
			}
			if (this.systemLanguageCode != setTdlibParameters.systemLanguageCode) {
				return false;
			}
			if (this.deviceModel != setTdlibParameters.deviceModel) {
				return false;
			}
			if (this.systemVersion != setTdlibParameters.systemVersion) {
				return false;
			}
			if (this.applicationVersion != setTdlibParameters.applicationVersion) {
				return false;
			}
			if (this.enableStorageOptimizer != setTdlibParameters.enableStorageOptimizer) {
				return false;
			}
			if (this.ignoreFileNames != setTdlibParameters.ignoreFileNames) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.useTestDc);
			result = result * 31 + (this.databaseDirectory == null ? 0 : this.databaseDirectory.hashCode());
			result = result * 31 + (this.filesDirectory == null ? 0 : this.filesDirectory.hashCode());
			result = result * 31 + (Arrays.hashCode(this.databaseEncryptionKey));
			result = result * 31 + (this.apiHash == null ? 0 : this.apiHash.hashCode());
			result = result * 31 + (this.systemLanguageCode == null ? 0 : this.systemLanguageCode.hashCode());
			result = result * 31 + (this.deviceModel == null ? 0 : this.deviceModel.hashCode());
			result = result * 31 + (this.systemVersion == null ? 0 : this.systemVersion.hashCode());
			result = result * 31 + (this.applicationVersion == null ? 0 : this.applicationVersion.hashCode());
			return result;
		}
	}

	/**
	 * Changes a personal profile photo of a contact user.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetUserPersonalProfilePhoto extends Function<Ok> {


		/**
		 * User identifier.
		**/
		public long userId;

		/**
		 * Profile photo to set; pass null to delete the photo; inputChatPhotoPrevious isn&#039;t supported in this function.
		**/
		public InputChatPhoto photo;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 464136438;

		/**
		 * Changes a personal profile photo of a contact user.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetUserPersonalProfilePhoto() {}

		/**
		 * Changes a personal profile photo of a contact user.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param userId User identifier.
		 * @param photo Profile photo to set; pass null to delete the photo; inputChatPhotoPrevious isn&#039;t supported in this function.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetUserPersonalProfilePhoto(long userId, InputChatPhoto photo) {
			this.userId = userId;
			this.photo = photo;
		}

		/**
		 * Changes a personal profile photo of a contact user.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetUserPersonalProfilePhoto(DataInput input) throws IOException {
			this.userId = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputChatPhotoPrevious.CONSTRUCTOR: this.photo = new InputChatPhotoPrevious(input); break;
					case InputChatPhotoStatic.CONSTRUCTOR: this.photo = new InputChatPhotoStatic(input); break;
					case InputChatPhotoAnimation.CONSTRUCTOR: this.photo = new InputChatPhotoAnimation(input); break;
					case InputChatPhotoSticker.CONSTRUCTOR: this.photo = new InputChatPhotoSticker(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetUserPersonalProfilePhoto.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetUserPersonalProfilePhoto.CONSTRUCTOR);
			output.writeLong(this.userId);
			if (this.photo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.photo.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetUserPersonalProfilePhoto setUserPersonalProfilePhoto = (SetUserPersonalProfilePhoto) o;
			if (this.userId != setUserPersonalProfilePhoto.userId) {
				return false;
			}
			if (!Objects.equals(this.photo, setUserPersonalProfilePhoto.photo)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.userId);
			result = result * 31 + (this.photo == null ? 0 : this.photo.hashCode());
			return result;
		}
	}

	/**
	 * Changes user privacy settings.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetUserPrivacySettingRules extends Function<Ok> {


		/**
		 * The privacy setting.
		**/
		public UserPrivacySetting setting;

		/**
		 * The new privacy rules.
		**/
		public UserPrivacySettingRules rules;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -473812741;

		/**
		 * Changes user privacy settings.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetUserPrivacySettingRules() {}

		/**
		 * Changes user privacy settings.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param setting The privacy setting.
		 * @param rules The new privacy rules.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetUserPrivacySettingRules(UserPrivacySetting setting, UserPrivacySettingRules rules) {
			this.setting = setting;
			this.rules = rules;
		}

		/**
		 * Changes user privacy settings.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetUserPrivacySettingRules(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case UserPrivacySettingShowStatus.CONSTRUCTOR: this.setting = new UserPrivacySettingShowStatus(input); break;
					case UserPrivacySettingShowProfilePhoto.CONSTRUCTOR: this.setting = new UserPrivacySettingShowProfilePhoto(input); break;
					case UserPrivacySettingShowLinkInForwardedMessages.CONSTRUCTOR: this.setting = new UserPrivacySettingShowLinkInForwardedMessages(input); break;
					case UserPrivacySettingShowPhoneNumber.CONSTRUCTOR: this.setting = new UserPrivacySettingShowPhoneNumber(input); break;
					case UserPrivacySettingAllowChatInvites.CONSTRUCTOR: this.setting = new UserPrivacySettingAllowChatInvites(input); break;
					case UserPrivacySettingAllowCalls.CONSTRUCTOR: this.setting = new UserPrivacySettingAllowCalls(input); break;
					case UserPrivacySettingAllowPeerToPeerCalls.CONSTRUCTOR: this.setting = new UserPrivacySettingAllowPeerToPeerCalls(input); break;
					case UserPrivacySettingAllowFindingByPhoneNumber.CONSTRUCTOR: this.setting = new UserPrivacySettingAllowFindingByPhoneNumber(input); break;
					case UserPrivacySettingAllowPrivateVoiceAndVideoNoteMessages.CONSTRUCTOR: this.setting = new UserPrivacySettingAllowPrivateVoiceAndVideoNoteMessages(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				if (UserPrivacySettingRules.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.rules = new UserPrivacySettingRules(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetUserPrivacySettingRules.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetUserPrivacySettingRules.CONSTRUCTOR);
			if (this.setting == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.setting.serialize(output);
			}
			if (this.rules == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.rules.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetUserPrivacySettingRules setUserPrivacySettingRules = (SetUserPrivacySettingRules) o;
			if (!Objects.equals(this.setting, setUserPrivacySettingRules.setting)) {
				return false;
			}
			if (!Objects.equals(this.rules, setUserPrivacySettingRules.rules)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.setting == null ? 0 : this.setting.hashCode();
			result = result * 31 + (this.rules == null ? 0 : this.rules.hashCode());
			return result;
		}
	}

	/**
	 * Sets support information for the given user; for Telegram support
	 * only.
	 * <p> Returns {@link UserSupportInfo UserSupportInfo} </p>
	**/
	public static final class SetUserSupportInfo extends Function<UserSupportInfo> {


		/**
		 * User identifier.
		**/
		public long userId;

		/**
		 * New information message.
		**/
		public FormattedText message;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2088986621;

		/**
		 * Sets support information for the given user; for Telegram support only.
		 *
		 * <p> Returns {@link UserSupportInfo UserSupportInfo} </p>
		**/
		public SetUserSupportInfo() {}

		/**
		 * Sets support information for the given user; for Telegram support only.
		 *
		 * <p> Returns {@link UserSupportInfo UserSupportInfo} </p>
		 *
		 * @param userId User identifier.
		 * @param message New information message.
		 *
		 * <p> Returns {@link UserSupportInfo UserSupportInfo} </p>
		**/
		public SetUserSupportInfo(long userId, FormattedText message) {
			this.userId = userId;
			this.message = message;
		}

		/**
		 * Sets support information for the given user; for Telegram support only.
		 *
		 * <p> Returns {@link UserSupportInfo UserSupportInfo} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetUserSupportInfo(DataInput input) throws IOException {
			this.userId = input.readLong();
			if (input.readBoolean()) {
				if (FormattedText.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.message = new FormattedText(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetUserSupportInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetUserSupportInfo.CONSTRUCTOR);
			output.writeLong(this.userId);
			if (this.message == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.message.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetUserSupportInfo setUserSupportInfo = (SetUserSupportInfo) o;
			if (this.userId != setUserSupportInfo.userId) {
				return false;
			}
			if (!Objects.equals(this.message, setUserSupportInfo.message)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.userId);
			result = result * 31 + (this.message == null ? 0 : this.message.hashCode());
			return result;
		}
	}

	/**
	 * Changes the editable username of the current user.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetUsername extends Function<Ok> {


		/**
		 * The new value of the username. Use an empty string to remove the username. The username can&#039;t be completely removed if there is another active or disabled username.
		**/
		public String username;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 439901214;

		/**
		 * Changes the editable username of the current user.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetUsername() {}

		/**
		 * Changes the editable username of the current user.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param username The new value of the username. Use an empty string to remove the username. The username can&#039;t be completely removed if there is another active or disabled username.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetUsername(String username) {
			this.username = username;
		}

		/**
		 * Changes the editable username of the current user.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetUsername(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] usernameTmp = new byte[input.readInt()];
				input.readFully(usernameTmp);
				this.username = new String(usernameTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetUsername.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetUsername.CONSTRUCTOR);
			if (this.username == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] usernameTmp = this.username.getBytes(StandardCharsets.UTF_8);
				output.writeInt(usernameTmp.length);
				output.write(usernameTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetUsername setUsername = (SetUsername) o;
			if (this.username != setUsername.username) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.username == null ? 0 : this.username.hashCode();
		}
	}

	/**
	 * Changes default participant identifier, on whose behalf a video chat
	 * in the chat will be joined.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SetVideoChatDefaultParticipant extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Default group call participant identifier to join the video chats.
		**/
		public MessageSender defaultParticipantId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -240749901;

		/**
		 * Changes default participant identifier, on whose behalf a video chat in the chat will be joined.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetVideoChatDefaultParticipant() {}

		/**
		 * Changes default participant identifier, on whose behalf a video chat in the chat will be joined.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param defaultParticipantId Default group call participant identifier to join the video chats.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SetVideoChatDefaultParticipant(long chatId, MessageSender defaultParticipantId) {
			this.chatId = chatId;
			this.defaultParticipantId = defaultParticipantId;
		}

		/**
		 * Changes default participant identifier, on whose behalf a video chat in the chat will be joined.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SetVideoChatDefaultParticipant(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case MessageSenderUser.CONSTRUCTOR: this.defaultParticipantId = new MessageSenderUser(input); break;
					case MessageSenderChat.CONSTRUCTOR: this.defaultParticipantId = new MessageSenderChat(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SetVideoChatDefaultParticipant.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SetVideoChatDefaultParticipant.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.defaultParticipantId == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.defaultParticipantId.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SetVideoChatDefaultParticipant setVideoChatDefaultParticipant = (SetVideoChatDefaultParticipant) o;
			if (this.chatId != setVideoChatDefaultParticipant.chatId) {
				return false;
			}
			if (!Objects.equals(this.defaultParticipantId, setVideoChatDefaultParticipant.defaultParticipantId)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.defaultParticipantId == null ? 0 : this.defaultParticipantId.hashCode());
			return result;
		}
	}

	/**
	 * Shares a chat after pressing a keyboardButtonTypeRequestChat button
	 * with the bot.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ShareChatWithBot extends Function<Ok> {


		/**
		 * Identifier of the chat with the bot.
		**/
		public long chatId;

		/**
		 * Identifier of the message with the button.
		**/
		public long messageId;

		/**
		 * Identifier of the button.
		**/
		public int buttonId;

		/**
		 * Identifier of the shared chat.
		**/
		public long sharedChatId;

		/**
		 * Pass true to check that the chat can be shared by the button instead of actually sharing it. Doesn&#039;t check botIsMember and botAdministratorRights restrictions. If the bot must be a member, then all chats from getGroupsInCommon and all chats, where the user can add the bot, are suitable. In the latter case the bot will be automatically added to the chat. If the bot must be an administrator, then all chats, where the bot already has requested rights or can be added to administrators by the user, are suitable. In the latter case the bot will be automatically granted requested rights.
		**/
		public boolean onlyCheck;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1504507166;

		/**
		 * Shares a chat after pressing a keyboardButtonTypeRequestChat button with the bot.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ShareChatWithBot() {}

		/**
		 * Shares a chat after pressing a keyboardButtonTypeRequestChat button with the bot.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Identifier of the chat with the bot.
		 * @param messageId Identifier of the message with the button.
		 * @param buttonId Identifier of the button.
		 * @param sharedChatId Identifier of the shared chat.
		 * @param onlyCheck Pass true to check that the chat can be shared by the button instead of actually sharing it. Doesn&#039;t check botIsMember and botAdministratorRights restrictions. If the bot must be a member, then all chats from getGroupsInCommon and all chats, where the user can add the bot, are suitable. In the latter case the bot will be automatically added to the chat. If the bot must be an administrator, then all chats, where the bot already has requested rights or can be added to administrators by the user, are suitable. In the latter case the bot will be automatically granted requested rights.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ShareChatWithBot(long chatId,
				long messageId,
				int buttonId,
				long sharedChatId,
				boolean onlyCheck) {
			this.chatId = chatId;
			this.messageId = messageId;
			this.buttonId = buttonId;
			this.sharedChatId = sharedChatId;
			this.onlyCheck = onlyCheck;
		}

		/**
		 * Shares a chat after pressing a keyboardButtonTypeRequestChat button with the bot.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ShareChatWithBot(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
			this.buttonId = input.readInt();
			this.sharedChatId = input.readLong();
			this.onlyCheck = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ShareChatWithBot.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ShareChatWithBot.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
			output.writeInt(this.buttonId);
			output.writeLong(this.sharedChatId);
			output.writeBoolean(this.onlyCheck);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ShareChatWithBot shareChatWithBot = (ShareChatWithBot) o;
			if (this.chatId != shareChatWithBot.chatId) {
				return false;
			}
			if (this.messageId != shareChatWithBot.messageId) {
				return false;
			}
			if (this.buttonId != shareChatWithBot.buttonId) {
				return false;
			}
			if (this.sharedChatId != shareChatWithBot.sharedChatId) {
				return false;
			}
			if (this.onlyCheck != shareChatWithBot.onlyCheck) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Shares the phone number of the current user with a mutual contact.
	 * Supposed to be called when the user clicks on
	 * chatActionBarSharePhoneNumber.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SharePhoneNumber extends Function<Ok> {


		/**
		 * Identifier of the user with whom to share the phone number. The user must be a mutual contact.
		**/
		public long userId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1097130069;

		/**
		 * Shares the phone number of the current user with a mutual contact. Supposed to be called when the user clicks on chatActionBarSharePhoneNumber.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SharePhoneNumber() {}

		/**
		 * Shares the phone number of the current user with a mutual contact. Supposed to be called when the user clicks on chatActionBarSharePhoneNumber.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param userId Identifier of the user with whom to share the phone number. The user must be a mutual contact.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SharePhoneNumber(long userId) {
			this.userId = userId;
		}

		/**
		 * Shares the phone number of the current user with a mutual contact. Supposed to be called when the user clicks on chatActionBarSharePhoneNumber.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SharePhoneNumber(DataInput input) throws IOException {
			this.userId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SharePhoneNumber.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SharePhoneNumber.CONSTRUCTOR);
			output.writeLong(this.userId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SharePhoneNumber sharePhoneNumber = (SharePhoneNumber) o;
			if (this.userId != sharePhoneNumber.userId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.userId);
		}
	}

	/**
	 * Shares a user after pressing a keyboardButtonTypeRequestUser button
	 * with the bot.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ShareUserWithBot extends Function<Ok> {


		/**
		 * Identifier of the chat with the bot.
		**/
		public long chatId;

		/**
		 * Identifier of the message with the button.
		**/
		public long messageId;

		/**
		 * Identifier of the button.
		**/
		public int buttonId;

		/**
		 * Identifier of the shared user.
		**/
		public long sharedUserId;

		/**
		 * Pass true to check that the user can be shared by the button instead of actually sharing them.
		**/
		public boolean onlyCheck;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -248315940;

		/**
		 * Shares a user after pressing a keyboardButtonTypeRequestUser button with the bot.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ShareUserWithBot() {}

		/**
		 * Shares a user after pressing a keyboardButtonTypeRequestUser button with the bot.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Identifier of the chat with the bot.
		 * @param messageId Identifier of the message with the button.
		 * @param buttonId Identifier of the button.
		 * @param sharedUserId Identifier of the shared user.
		 * @param onlyCheck Pass true to check that the user can be shared by the button instead of actually sharing them.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ShareUserWithBot(long chatId,
				long messageId,
				int buttonId,
				long sharedUserId,
				boolean onlyCheck) {
			this.chatId = chatId;
			this.messageId = messageId;
			this.buttonId = buttonId;
			this.sharedUserId = sharedUserId;
			this.onlyCheck = onlyCheck;
		}

		/**
		 * Shares a user after pressing a keyboardButtonTypeRequestUser button with the bot.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ShareUserWithBot(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
			this.buttonId = input.readInt();
			this.sharedUserId = input.readLong();
			this.onlyCheck = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ShareUserWithBot.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ShareUserWithBot.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
			output.writeInt(this.buttonId);
			output.writeLong(this.sharedUserId);
			output.writeBoolean(this.onlyCheck);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ShareUserWithBot shareUserWithBot = (ShareUserWithBot) o;
			if (this.chatId != shareUserWithBot.chatId) {
				return false;
			}
			if (this.messageId != shareUserWithBot.messageId) {
				return false;
			}
			if (this.buttonId != shareUserWithBot.buttonId) {
				return false;
			}
			if (this.sharedUserId != shareUserWithBot.sharedUserId) {
				return false;
			}
			if (this.onlyCheck != shareUserWithBot.onlyCheck) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Starts recording of an active group call. Requires
	 * groupCall.canBeManaged group call flag.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class StartGroupCallRecording extends Function<Ok> {


		/**
		 * Group call identifier.
		**/
		public int groupCallId;

		/**
		 * Group call recording title; 0-64 characters.
		**/
		public String title;

		/**
		 * Pass true to record a video file instead of an audio file.
		**/
		public boolean recordVideo;

		/**
		 * Pass true to use portrait orientation for video instead of landscape one.
		**/
		public boolean usePortraitOrientation;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1757774971;

		/**
		 * Starts recording of an active group call. Requires groupCall.canBeManaged group call flag.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public StartGroupCallRecording() {}

		/**
		 * Starts recording of an active group call. Requires groupCall.canBeManaged group call flag.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param groupCallId Group call identifier.
		 * @param title Group call recording title; 0-64 characters.
		 * @param recordVideo Pass true to record a video file instead of an audio file.
		 * @param usePortraitOrientation Pass true to use portrait orientation for video instead of landscape one.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public StartGroupCallRecording(int groupCallId,
				String title,
				boolean recordVideo,
				boolean usePortraitOrientation) {
			this.groupCallId = groupCallId;
			this.title = title;
			this.recordVideo = recordVideo;
			this.usePortraitOrientation = usePortraitOrientation;
		}

		/**
		 * Starts recording of an active group call. Requires groupCall.canBeManaged group call flag.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public StartGroupCallRecording(DataInput input) throws IOException {
			this.groupCallId = input.readInt();
			if (input.readBoolean()) {
				byte[] titleTmp = new byte[input.readInt()];
				input.readFully(titleTmp);
				this.title = new String(titleTmp, StandardCharsets.UTF_8);
			}
			this.recordVideo = input.readBoolean();
			this.usePortraitOrientation = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return StartGroupCallRecording.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(StartGroupCallRecording.CONSTRUCTOR);
			output.writeInt(this.groupCallId);
			if (this.title == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] titleTmp = this.title.getBytes(StandardCharsets.UTF_8);
				output.writeInt(titleTmp.length);
				output.write(titleTmp);
			}
			output.writeBoolean(this.recordVideo);
			output.writeBoolean(this.usePortraitOrientation);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			StartGroupCallRecording startGroupCallRecording = (StartGroupCallRecording) o;
			if (this.groupCallId != startGroupCallRecording.groupCallId) {
				return false;
			}
			if (this.title != startGroupCallRecording.title) {
				return false;
			}
			if (this.recordVideo != startGroupCallRecording.recordVideo) {
				return false;
			}
			if (this.usePortraitOrientation != startGroupCallRecording.usePortraitOrientation) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.groupCallId);
			result = result * 31 + (this.title == null ? 0 : this.title.hashCode());
			return result;
		}
	}

	/**
	 * Starts screen sharing in a joined group call. Returns join response
	 * payload for tgcalls.
	 * <p> Returns {@link Text Text} </p>
	**/
	public static final class StartGroupCallScreenSharing extends Function<Text> {


		/**
		 * Group call identifier.
		**/
		public int groupCallId;

		/**
		 * Screen sharing audio channel synchronization source identifier; received from tgcalls.
		**/
		public int audioSourceId;

		/**
		 * Group call join payload; received from tgcalls.
		**/
		public String payload;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -884068051;

		/**
		 * Starts screen sharing in a joined group call. Returns join response payload for tgcalls.
		 *
		 * <p> Returns {@link Text Text} </p>
		**/
		public StartGroupCallScreenSharing() {}

		/**
		 * Starts screen sharing in a joined group call. Returns join response payload for tgcalls.
		 *
		 * <p> Returns {@link Text Text} </p>
		 *
		 * @param groupCallId Group call identifier.
		 * @param audioSourceId Screen sharing audio channel synchronization source identifier; received from tgcalls.
		 * @param payload Group call join payload; received from tgcalls.
		 *
		 * <p> Returns {@link Text Text} </p>
		**/
		public StartGroupCallScreenSharing(int groupCallId, int audioSourceId, String payload) {
			this.groupCallId = groupCallId;
			this.audioSourceId = audioSourceId;
			this.payload = payload;
		}

		/**
		 * Starts screen sharing in a joined group call. Returns join response payload for tgcalls.
		 *
		 * <p> Returns {@link Text Text} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public StartGroupCallScreenSharing(DataInput input) throws IOException {
			this.groupCallId = input.readInt();
			this.audioSourceId = input.readInt();
			if (input.readBoolean()) {
				byte[] payloadTmp = new byte[input.readInt()];
				input.readFully(payloadTmp);
				this.payload = new String(payloadTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return StartGroupCallScreenSharing.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(StartGroupCallScreenSharing.CONSTRUCTOR);
			output.writeInt(this.groupCallId);
			output.writeInt(this.audioSourceId);
			if (this.payload == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] payloadTmp = this.payload.getBytes(StandardCharsets.UTF_8);
				output.writeInt(payloadTmp.length);
				output.write(payloadTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			StartGroupCallScreenSharing startGroupCallScreenSharing = (StartGroupCallScreenSharing) o;
			if (this.groupCallId != startGroupCallScreenSharing.groupCallId) {
				return false;
			}
			if (this.audioSourceId != startGroupCallScreenSharing.audioSourceId) {
				return false;
			}
			if (this.payload != startGroupCallScreenSharing.payload) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.groupCallId);
			result = result * 31 + (this.payload == null ? 0 : this.payload.hashCode());
			return result;
		}
	}

	/**
	 * Starts a scheduled group call.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class StartScheduledGroupCall extends Function<Ok> {


		/**
		 * Group call identifier.
		**/
		public int groupCallId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1519938838;

		/**
		 * Starts a scheduled group call.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public StartScheduledGroupCall() {}

		/**
		 * Starts a scheduled group call.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param groupCallId Group call identifier.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public StartScheduledGroupCall(int groupCallId) {
			this.groupCallId = groupCallId;
		}

		/**
		 * Starts a scheduled group call.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public StartScheduledGroupCall(DataInput input) throws IOException {
			this.groupCallId = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return StartScheduledGroupCall.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(StartScheduledGroupCall.CONSTRUCTOR);
			output.writeInt(this.groupCallId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			StartScheduledGroupCall startScheduledGroupCall = (StartScheduledGroupCall) o;
			if (this.groupCallId != startScheduledGroupCall.groupCallId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.groupCallId);
		}
	}

	/**
	 * Stops a poll. A poll in a message can be stopped when the message has
	 * canBeEdited flag set.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class StopPoll extends Function<Ok> {


		/**
		 * Identifier of the chat to which the poll belongs.
		**/
		public long chatId;

		/**
		 * Identifier of the message containing the poll.
		**/
		public long messageId;

		/**
		 * The new message reply markup; pass null if none; for bots only.
		**/
		public ReplyMarkup replyMarkup;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1659374253;

		/**
		 * Stops a poll. A poll in a message can be stopped when the message has canBeEdited flag set.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public StopPoll() {}

		/**
		 * Stops a poll. A poll in a message can be stopped when the message has canBeEdited flag set.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Identifier of the chat to which the poll belongs.
		 * @param messageId Identifier of the message containing the poll.
		 * @param replyMarkup The new message reply markup; pass null if none; for bots only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public StopPoll(long chatId, long messageId, ReplyMarkup replyMarkup) {
			this.chatId = chatId;
			this.messageId = messageId;
			this.replyMarkup = replyMarkup;
		}

		/**
		 * Stops a poll. A poll in a message can be stopped when the message has canBeEdited flag set.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public StopPoll(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ReplyMarkupRemoveKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupRemoveKeyboard(input); break;
					case ReplyMarkupForceReply.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupForceReply(input); break;
					case ReplyMarkupShowKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupShowKeyboard(input); break;
					case ReplyMarkupInlineKeyboard.CONSTRUCTOR: this.replyMarkup = new ReplyMarkupInlineKeyboard(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return StopPoll.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(StopPoll.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
			if (this.replyMarkup == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.replyMarkup.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			StopPoll stopPoll = (StopPoll) o;
			if (this.chatId != stopPoll.chatId) {
				return false;
			}
			if (this.messageId != stopPoll.messageId) {
				return false;
			}
			if (!Objects.equals(this.replyMarkup, stopPoll.replyMarkup)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.replyMarkup == null ? 0 : this.replyMarkup.hashCode());
			return result;
		}
	}

	/**
	 * Suggests a profile photo to another regular user with common messages.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SuggestUserProfilePhoto extends Function<Ok> {


		/**
		 * User identifier.
		**/
		public long userId;

		/**
		 * Profile photo to suggest; inputChatPhotoPrevious isn&#039;t supported in this function.
		**/
		public InputChatPhoto photo;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1788742557;

		/**
		 * Suggests a profile photo to another regular user with common messages.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SuggestUserProfilePhoto() {}

		/**
		 * Suggests a profile photo to another regular user with common messages.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param userId User identifier.
		 * @param photo Profile photo to suggest; inputChatPhotoPrevious isn&#039;t supported in this function.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SuggestUserProfilePhoto(long userId, InputChatPhoto photo) {
			this.userId = userId;
			this.photo = photo;
		}

		/**
		 * Suggests a profile photo to another regular user with common messages.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SuggestUserProfilePhoto(DataInput input) throws IOException {
			this.userId = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputChatPhotoPrevious.CONSTRUCTOR: this.photo = new InputChatPhotoPrevious(input); break;
					case InputChatPhotoStatic.CONSTRUCTOR: this.photo = new InputChatPhotoStatic(input); break;
					case InputChatPhotoAnimation.CONSTRUCTOR: this.photo = new InputChatPhotoAnimation(input); break;
					case InputChatPhotoSticker.CONSTRUCTOR: this.photo = new InputChatPhotoSticker(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SuggestUserProfilePhoto.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SuggestUserProfilePhoto.CONSTRUCTOR);
			output.writeLong(this.userId);
			if (this.photo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.photo.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SuggestUserProfilePhoto suggestUserProfilePhoto = (SuggestUserProfilePhoto) o;
			if (this.userId != suggestUserProfilePhoto.userId) {
				return false;
			}
			if (!Objects.equals(this.photo, suggestUserProfilePhoto.photo)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.userId);
			result = result * 31 + (this.photo == null ? 0 : this.photo.hashCode());
			return result;
		}
	}

	/**
	 * Fetches the latest versions of all strings from a language pack in
	 * the current localization target from the server. This method
	 * doesn&#039;t need to be called explicitly for the current used/base
	 * language packs. Can be called before authorization.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class SynchronizeLanguagePack extends Function<Ok> {


		/**
		 * Language pack identifier.
		**/
		public String languagePackId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2065307858;

		/**
		 * Fetches the latest versions of all strings from a language pack in the current localization target from the server. This method doesn&#039;t need to be called explicitly for the current used/base language packs. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SynchronizeLanguagePack() {}

		/**
		 * Fetches the latest versions of all strings from a language pack in the current localization target from the server. This method doesn&#039;t need to be called explicitly for the current used/base language packs. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param languagePackId Language pack identifier.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public SynchronizeLanguagePack(String languagePackId) {
			this.languagePackId = languagePackId;
		}

		/**
		 * Fetches the latest versions of all strings from a language pack in the current localization target from the server. This method doesn&#039;t need to be called explicitly for the current used/base language packs. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public SynchronizeLanguagePack(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] languagePackIdTmp = new byte[input.readInt()];
				input.readFully(languagePackIdTmp);
				this.languagePackId = new String(languagePackIdTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return SynchronizeLanguagePack.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(SynchronizeLanguagePack.CONSTRUCTOR);
			if (this.languagePackId == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] languagePackIdTmp = this.languagePackId.getBytes(StandardCharsets.UTF_8);
				output.writeInt(languagePackIdTmp.length);
				output.write(languagePackIdTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			SynchronizeLanguagePack synchronizeLanguagePack = (SynchronizeLanguagePack) o;
			if (this.languagePackId != synchronizeLanguagePack.languagePackId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.languagePackId == null ? 0 : this.languagePackId.hashCode();
		}
	}

	/**
	 * Terminates all other sessions of the current user.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class TerminateAllOtherSessions extends Function<Ok> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1874485523;

		/**
		 * Terminates all other sessions of the current user.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public TerminateAllOtherSessions() {}

		/**
		 * Terminates all other sessions of the current user.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/

		/**
		 * Terminates all other sessions of the current user.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TerminateAllOtherSessions(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TerminateAllOtherSessions.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TerminateAllOtherSessions.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return TerminateAllOtherSessions.CONSTRUCTOR;
		}
	}

	/**
	 * Terminates a session of the current user.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class TerminateSession extends Function<Ok> {


		/**
		 * Session identifier.
		**/
		public long sessionId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -407385812;

		/**
		 * Terminates a session of the current user.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public TerminateSession() {}

		/**
		 * Terminates a session of the current user.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param sessionId Session identifier.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public TerminateSession(long sessionId) {
			this.sessionId = sessionId;
		}

		/**
		 * Terminates a session of the current user.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TerminateSession(DataInput input) throws IOException {
			this.sessionId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TerminateSession.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TerminateSession.CONSTRUCTOR);
			output.writeLong(this.sessionId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			TerminateSession terminateSession = (TerminateSession) o;
			if (this.sessionId != terminateSession.sessionId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.sessionId);
		}
	}

	/**
	 * Returns the received bytes; for testing only. This is an offline
	 * method. Can be called before authorization.
	 * <p> Returns {@link TestBytes TestBytes} </p>
	**/
	public static final class TestCallBytes extends Function<TestBytes> {


		/**
		 * Bytes to return.
		**/
		public byte[] x;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -736011607;

		/**
		 * Returns the received bytes; for testing only. This is an offline method. Can be called before authorization.
		 *
		 * <p> Returns {@link TestBytes TestBytes} </p>
		**/
		public TestCallBytes() {}

		/**
		 * Returns the received bytes; for testing only. This is an offline method. Can be called before authorization.
		 *
		 * <p> Returns {@link TestBytes TestBytes} </p>
		 *
		 * @param x Bytes to return.
		 *
		 * <p> Returns {@link TestBytes TestBytes} </p>
		**/
		public TestCallBytes(byte[] x) {
			this.x = x;
		}

		/**
		 * Returns the received bytes; for testing only. This is an offline method. Can be called before authorization.
		 *
		 * <p> Returns {@link TestBytes TestBytes} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TestCallBytes(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.x = new byte[input.readInt()];
				input.readFully(this.x);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TestCallBytes.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TestCallBytes.CONSTRUCTOR);
			if (this.x == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.x.length);
				output.write(this.x);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			TestCallBytes testCallBytes = (TestCallBytes) o;
			if (this.x != testCallBytes.x) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.x);
		}
	}

	/**
	 * Does nothing; for testing only. This is an offline method. Can be
	 * called before authorization.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class TestCallEmpty extends Function<Ok> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -627291626;

		/**
		 * Does nothing; for testing only. This is an offline method. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public TestCallEmpty() {}

		/**
		 * Does nothing; for testing only. This is an offline method. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/

		/**
		 * Does nothing; for testing only. This is an offline method. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TestCallEmpty(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TestCallEmpty.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TestCallEmpty.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return TestCallEmpty.CONSTRUCTOR;
		}
	}

	/**
	 * Returns the received string; for testing only. This is an offline
	 * method. Can be called before authorization.
	 * <p> Returns {@link TestString TestString} </p>
	**/
	public static final class TestCallString extends Function<TestString> {


		/**
		 * String to return.
		**/
		public String x;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1732818385;

		/**
		 * Returns the received string; for testing only. This is an offline method. Can be called before authorization.
		 *
		 * <p> Returns {@link TestString TestString} </p>
		**/
		public TestCallString() {}

		/**
		 * Returns the received string; for testing only. This is an offline method. Can be called before authorization.
		 *
		 * <p> Returns {@link TestString TestString} </p>
		 *
		 * @param x String to return.
		 *
		 * <p> Returns {@link TestString TestString} </p>
		**/
		public TestCallString(String x) {
			this.x = x;
		}

		/**
		 * Returns the received string; for testing only. This is an offline method. Can be called before authorization.
		 *
		 * <p> Returns {@link TestString TestString} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TestCallString(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] xTmp = new byte[input.readInt()];
				input.readFully(xTmp);
				this.x = new String(xTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TestCallString.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TestCallString.CONSTRUCTOR);
			if (this.x == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] xTmp = this.x.getBytes(StandardCharsets.UTF_8);
				output.writeInt(xTmp.length);
				output.write(xTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			TestCallString testCallString = (TestCallString) o;
			if (this.x != testCallString.x) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.x == null ? 0 : this.x.hashCode();
		}
	}

	/**
	 * Returns the received vector of numbers; for testing only. This is an
	 * offline method. Can be called before authorization.
	 * <p> Returns {@link TestVectorInt TestVectorInt} </p>
	**/
	public static final class TestCallVectorInt extends Function<TestVectorInt> {


		/**
		 * Vector of numbers to return.
		**/
		public int[] x;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2137277793;

		/**
		 * Returns the received vector of numbers; for testing only. This is an offline method. Can be called before authorization.
		 *
		 * <p> Returns {@link TestVectorInt TestVectorInt} </p>
		**/
		public TestCallVectorInt() {}

		/**
		 * Returns the received vector of numbers; for testing only. This is an offline method. Can be called before authorization.
		 *
		 * <p> Returns {@link TestVectorInt TestVectorInt} </p>
		 *
		 * @param x Vector of numbers to return.
		 *
		 * <p> Returns {@link TestVectorInt TestVectorInt} </p>
		**/
		public TestCallVectorInt(int[] x) {
			this.x = x;
		}

		/**
		 * Returns the received vector of numbers; for testing only. This is an offline method. Can be called before authorization.
		 *
		 * <p> Returns {@link TestVectorInt TestVectorInt} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TestCallVectorInt(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.x = new int[input.readInt()];
				for (int i = 0; i < this.x.length; i++) {
					this.x[i] = input.readInt();
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TestCallVectorInt.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TestCallVectorInt.CONSTRUCTOR);
			if (this.x == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.x.length);
				for (int i = 0; i < this.x.length; i++) {
					output.writeInt(this.x[i]);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			TestCallVectorInt testCallVectorInt = (TestCallVectorInt) o;
			if (!Arrays.equals(this.x, testCallVectorInt.x)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.x);
		}
	}

	/**
	 * Returns the received vector of objects containing a number; for
	 * testing only. This is an offline method. Can be called before
	 * authorization.
	 * <p> Returns {@link TestVectorIntObject TestVectorIntObject} </p>
	**/
	public static final class TestCallVectorIntObject extends Function<TestVectorIntObject> {


		/**
		 * Vector of objects to return.
		**/
		public TestInt[] x;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1825428218;

		/**
		 * Returns the received vector of objects containing a number; for testing only. This is an offline method. Can be called before authorization.
		 *
		 * <p> Returns {@link TestVectorIntObject TestVectorIntObject} </p>
		**/
		public TestCallVectorIntObject() {}

		/**
		 * Returns the received vector of objects containing a number; for testing only. This is an offline method. Can be called before authorization.
		 *
		 * <p> Returns {@link TestVectorIntObject TestVectorIntObject} </p>
		 *
		 * @param x Vector of objects to return.
		 *
		 * <p> Returns {@link TestVectorIntObject TestVectorIntObject} </p>
		**/
		public TestCallVectorIntObject(TestInt[] x) {
			this.x = x;
		}

		/**
		 * Returns the received vector of objects containing a number; for testing only. This is an offline method. Can be called before authorization.
		 *
		 * <p> Returns {@link TestVectorIntObject TestVectorIntObject} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TestCallVectorIntObject(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.x = new TestInt[input.readInt()];
				for (int i = 0; i < this.x.length; i++) {
					if (TestInt.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.x[i] = new TestInt(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TestCallVectorIntObject.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TestCallVectorIntObject.CONSTRUCTOR);
			if (this.x == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.x.length);
				for (int i = 0; i < this.x.length; i++) {
					this.x[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			TestCallVectorIntObject testCallVectorIntObject = (TestCallVectorIntObject) o;
			if (!Arrays.equals(this.x, testCallVectorIntObject.x)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.x);
		}
	}

	/**
	 * Returns the received vector of strings; for testing only. This is an
	 * offline method. Can be called before authorization.
	 * <p> Returns {@link TestVectorString TestVectorString} </p>
	**/
	public static final class TestCallVectorString extends Function<TestVectorString> {


		/**
		 * Vector of strings to return.
		**/
		public String[] x;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -408600900;

		/**
		 * Returns the received vector of strings; for testing only. This is an offline method. Can be called before authorization.
		 *
		 * <p> Returns {@link TestVectorString TestVectorString} </p>
		**/
		public TestCallVectorString() {}

		/**
		 * Returns the received vector of strings; for testing only. This is an offline method. Can be called before authorization.
		 *
		 * <p> Returns {@link TestVectorString TestVectorString} </p>
		 *
		 * @param x Vector of strings to return.
		 *
		 * <p> Returns {@link TestVectorString TestVectorString} </p>
		**/
		public TestCallVectorString(String[] x) {
			this.x = x;
		}

		/**
		 * Returns the received vector of strings; for testing only. This is an offline method. Can be called before authorization.
		 *
		 * <p> Returns {@link TestVectorString TestVectorString} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TestCallVectorString(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.x = new String[input.readInt()];
				for (int i = 0; i < this.x.length; i++) {
					byte[] xTmp = new byte[input.readInt()];
					input.readFully(xTmp);
					this.x[i] = new String(xTmp, StandardCharsets.UTF_8);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TestCallVectorString.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TestCallVectorString.CONSTRUCTOR);
			if (this.x == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.x.length);
				for (int i = 0; i < this.x.length; i++) {
					byte[] xTmp = this.x[i].getBytes(StandardCharsets.UTF_8);
					output.writeInt(xTmp.length);
					output.write(xTmp);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			TestCallVectorString testCallVectorString = (TestCallVectorString) o;
			if (!Arrays.equals(this.x, testCallVectorString.x)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.x);
		}
	}

	/**
	 * Returns the received vector of objects containing a string; for
	 * testing only. This is an offline method. Can be called before
	 * authorization.
	 * <p> Returns {@link TestVectorStringObject TestVectorStringObject} </p>
	**/
	public static final class TestCallVectorStringObject extends Function<TestVectorStringObject> {


		/**
		 * Vector of objects to return.
		**/
		public TestString[] x;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1527666429;

		/**
		 * Returns the received vector of objects containing a string; for testing only. This is an offline method. Can be called before authorization.
		 *
		 * <p> Returns {@link TestVectorStringObject TestVectorStringObject} </p>
		**/
		public TestCallVectorStringObject() {}

		/**
		 * Returns the received vector of objects containing a string; for testing only. This is an offline method. Can be called before authorization.
		 *
		 * <p> Returns {@link TestVectorStringObject TestVectorStringObject} </p>
		 *
		 * @param x Vector of objects to return.
		 *
		 * <p> Returns {@link TestVectorStringObject TestVectorStringObject} </p>
		**/
		public TestCallVectorStringObject(TestString[] x) {
			this.x = x;
		}

		/**
		 * Returns the received vector of objects containing a string; for testing only. This is an offline method. Can be called before authorization.
		 *
		 * <p> Returns {@link TestVectorStringObject TestVectorStringObject} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TestCallVectorStringObject(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.x = new TestString[input.readInt()];
				for (int i = 0; i < this.x.length; i++) {
					if (TestString.CONSTRUCTOR != input.readInt()) {
						throw new UnsupportedOperationException();
					}
					this.x[i] = new TestString(input);
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TestCallVectorStringObject.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TestCallVectorStringObject.CONSTRUCTOR);
			if (this.x == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.x.length);
				for (int i = 0; i < this.x.length; i++) {
					this.x[i].serialize(output);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			TestCallVectorStringObject testCallVectorStringObject = (TestCallVectorStringObject) o;
			if (!Arrays.equals(this.x, testCallVectorStringObject.x)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.x);
		}
	}

	/**
	 * Forces an updates.getDifference call to the Telegram servers; for
	 * testing only.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class TestGetDifference extends Function<Ok> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1747084069;

		/**
		 * Forces an updates.getDifference call to the Telegram servers; for testing only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public TestGetDifference() {}

		/**
		 * Forces an updates.getDifference call to the Telegram servers; for testing only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/

		/**
		 * Forces an updates.getDifference call to the Telegram servers; for testing only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TestGetDifference(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TestGetDifference.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TestGetDifference.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return TestGetDifference.CONSTRUCTOR;
		}
	}

	/**
	 * Sends a simple network request to the Telegram servers; for testing
	 * only. Can be called before authorization.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class TestNetwork extends Function<Ok> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1343998901;

		/**
		 * Sends a simple network request to the Telegram servers; for testing only. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public TestNetwork() {}

		/**
		 * Sends a simple network request to the Telegram servers; for testing only. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/

		/**
		 * Sends a simple network request to the Telegram servers; for testing only. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TestNetwork(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TestNetwork.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TestNetwork.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return TestNetwork.CONSTRUCTOR;
		}
	}

	/**
	 * Sends a simple network request to the Telegram servers via proxy; for
	 * testing only. Can be called before authorization.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class TestProxy extends Function<Ok> {


		/**
		 * Proxy server IP address.
		**/
		public String server;

		/**
		 * Proxy server port.
		**/
		public int port;

		/**
		 * Proxy type.
		**/
		public ProxyType type;

		/**
		 * Identifier of a datacenter with which to test connection.
		**/
		public int dcId;

		/**
		 * The maximum overall timeout for the request.
		**/
		public double timeout;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1197366626;

		/**
		 * Sends a simple network request to the Telegram servers via proxy; for testing only. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public TestProxy() {}

		/**
		 * Sends a simple network request to the Telegram servers via proxy; for testing only. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param server Proxy server IP address.
		 * @param port Proxy server port.
		 * @param type Proxy type.
		 * @param dcId Identifier of a datacenter with which to test connection.
		 * @param timeout The maximum overall timeout for the request.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public TestProxy(String server,
				int port,
				ProxyType type,
				int dcId,
				double timeout) {
			this.server = server;
			this.port = port;
			this.type = type;
			this.dcId = dcId;
			this.timeout = timeout;
		}

		/**
		 * Sends a simple network request to the Telegram servers via proxy; for testing only. Can be called before authorization.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TestProxy(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] serverTmp = new byte[input.readInt()];
				input.readFully(serverTmp);
				this.server = new String(serverTmp, StandardCharsets.UTF_8);
			}
			this.port = input.readInt();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ProxyTypeSocks5.CONSTRUCTOR: this.type = new ProxyTypeSocks5(input); break;
					case ProxyTypeHttp.CONSTRUCTOR: this.type = new ProxyTypeHttp(input); break;
					case ProxyTypeMtproto.CONSTRUCTOR: this.type = new ProxyTypeMtproto(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.dcId = input.readInt();
			this.timeout = input.readDouble();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TestProxy.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TestProxy.CONSTRUCTOR);
			if (this.server == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] serverTmp = this.server.getBytes(StandardCharsets.UTF_8);
				output.writeInt(serverTmp.length);
				output.write(serverTmp);
			}
			output.writeInt(this.port);
			if (this.type == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.type.serialize(output);
			}
			output.writeInt(this.dcId);
			output.writeDouble(this.timeout);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			TestProxy testProxy = (TestProxy) o;
			if (this.server != testProxy.server) {
				return false;
			}
			if (this.port != testProxy.port) {
				return false;
			}
			if (!Objects.equals(this.type, testProxy.type)) {
				return false;
			}
			if (this.dcId != testProxy.dcId) {
				return false;
			}
			if (this.timeout != testProxy.timeout) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.port);
			result = result * 31 + (this.server == null ? 0 : this.server.hashCode());
			result = result * 31 + (this.type == null ? 0 : this.type.hashCode());
			return result;
		}
	}

	/**
	 * Returns the specified error and ensures that the Error object is
	 * used; for testing only. Can be called synchronously.
	 * <p> Returns {@link Error Error} </p>
	**/
	public static final class TestReturnError extends Function<Error> {


		/**
		 * The error to be returned.
		**/
		public Error error;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 455179506;

		/**
		 * Returns the specified error and ensures that the Error object is used; for testing only. Can be called synchronously.
		 *
		 * <p> Returns {@link Error Error} </p>
		**/
		public TestReturnError() {}

		/**
		 * Returns the specified error and ensures that the Error object is used; for testing only. Can be called synchronously.
		 *
		 * <p> Returns {@link Error Error} </p>
		 *
		 * @param error The error to be returned.
		 *
		 * <p> Returns {@link Error Error} </p>
		**/
		public TestReturnError(Error error) {
			this.error = error;
		}

		/**
		 * Returns the specified error and ensures that the Error object is used; for testing only. Can be called synchronously.
		 *
		 * <p> Returns {@link Error Error} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TestReturnError(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (Error.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.error = new Error(input);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TestReturnError.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TestReturnError.CONSTRUCTOR);
			if (this.error == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.error.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			TestReturnError testReturnError = (TestReturnError) o;
			if (!Objects.equals(this.error, testReturnError.error)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.error == null ? 0 : this.error.hashCode();
		}
	}

	/**
	 * Returns the squared received number; for testing only. This is an
	 * offline method. Can be called before authorization.
	 * <p> Returns {@link TestInt TestInt} </p>
	**/
	public static final class TestSquareInt extends Function<TestInt> {


		/**
		 * Number to square.
		**/
		public int x;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -60135024;

		/**
		 * Returns the squared received number; for testing only. This is an offline method. Can be called before authorization.
		 *
		 * <p> Returns {@link TestInt TestInt} </p>
		**/
		public TestSquareInt() {}

		/**
		 * Returns the squared received number; for testing only. This is an offline method. Can be called before authorization.
		 *
		 * <p> Returns {@link TestInt TestInt} </p>
		 *
		 * @param x Number to square.
		 *
		 * <p> Returns {@link TestInt TestInt} </p>
		**/
		public TestSquareInt(int x) {
			this.x = x;
		}

		/**
		 * Returns the squared received number; for testing only. This is an offline method. Can be called before authorization.
		 *
		 * <p> Returns {@link TestInt TestInt} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TestSquareInt(DataInput input) throws IOException {
			this.x = input.readInt();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TestSquareInt.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TestSquareInt.CONSTRUCTOR);
			output.writeInt(this.x);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			TestSquareInt testSquareInt = (TestSquareInt) o;
			if (this.x != testSquareInt.x) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Integer.hashCode(this.x);
		}
	}

	/**
	 * Does nothing and ensures that the Update object is used; for testing
	 * only. This is an offline method. Can be called before authorization.
	 * <p> Returns {@link Update Update} </p>
	**/
	public static final class TestUseUpdate extends Function<Update> {


		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 717094686;

		/**
		 * Does nothing and ensures that the Update object is used; for testing only. This is an offline method. Can be called before authorization.
		 *
		 * <p> Returns {@link Update Update} </p>
		**/
		public TestUseUpdate() {}

		/**
		 * Does nothing and ensures that the Update object is used; for testing only. This is an offline method. Can be called before authorization.
		 *
		 * <p> Returns {@link Update Update} </p>
		 *
		 *
		 * <p> Returns {@link Update Update} </p>
		**/

		/**
		 * Does nothing and ensures that the Update object is used; for testing only. This is an offline method. Can be called before authorization.
		 *
		 * <p> Returns {@link Update Update} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TestUseUpdate(DataInput input) throws IOException {
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TestUseUpdate.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TestUseUpdate.CONSTRUCTOR);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return TestUseUpdate.CONSTRUCTOR;
		}
	}

	/**
	 * Changes pause state of all files in the file download list.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ToggleAllDownloadsArePaused extends Function<Ok> {


		/**
		 * Pass true to pause all downloads; pass false to unpause them.
		**/
		public boolean arePaused;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1251512322;

		/**
		 * Changes pause state of all files in the file download list.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleAllDownloadsArePaused() {}

		/**
		 * Changes pause state of all files in the file download list.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param arePaused Pass true to pause all downloads; pass false to unpause them.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleAllDownloadsArePaused(boolean arePaused) {
			this.arePaused = arePaused;
		}

		/**
		 * Changes pause state of all files in the file download list.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ToggleAllDownloadsArePaused(DataInput input) throws IOException {
			this.arePaused = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ToggleAllDownloadsArePaused.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ToggleAllDownloadsArePaused.CONSTRUCTOR);
			output.writeBoolean(this.arePaused);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ToggleAllDownloadsArePaused toggleAllDownloadsArePaused = (ToggleAllDownloadsArePaused) o;
			if (this.arePaused != toggleAllDownloadsArePaused.arePaused) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Boolean.hashCode(this.arePaused);
		}
	}

	/**
	 * Adds or removes a bot to attachment menu. Bot can be added to
	 * attachment menu, only if userTypeBot.canBeAddedToAttachmentMenu ==
	 * true.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ToggleBotIsAddedToAttachmentMenu extends Function<Ok> {


		/**
		 * Bot&#039;s user identifier.
		**/
		public long botUserId;

		/**
		 * Pass true to add the bot to attachment menu; pass false to remove the bot from attachment menu.
		**/
		public boolean isAdded;

		/**
		 * Pass true if the current user allowed the bot to send them messages. Ignored if isAdded is false.
		**/
		public boolean allowWriteAccess;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1906712934;

		/**
		 * Adds or removes a bot to attachment menu. Bot can be added to attachment menu, only if userTypeBot.canBeAddedToAttachmentMenu == true.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleBotIsAddedToAttachmentMenu() {}

		/**
		 * Adds or removes a bot to attachment menu. Bot can be added to attachment menu, only if userTypeBot.canBeAddedToAttachmentMenu == true.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param botUserId Bot&#039;s user identifier.
		 * @param isAdded Pass true to add the bot to attachment menu; pass false to remove the bot from attachment menu.
		 * @param allowWriteAccess Pass true if the current user allowed the bot to send them messages. Ignored if isAdded is false.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleBotIsAddedToAttachmentMenu(long botUserId, boolean isAdded, boolean allowWriteAccess) {
			this.botUserId = botUserId;
			this.isAdded = isAdded;
			this.allowWriteAccess = allowWriteAccess;
		}

		/**
		 * Adds or removes a bot to attachment menu. Bot can be added to attachment menu, only if userTypeBot.canBeAddedToAttachmentMenu == true.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ToggleBotIsAddedToAttachmentMenu(DataInput input) throws IOException {
			this.botUserId = input.readLong();
			this.isAdded = input.readBoolean();
			this.allowWriteAccess = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ToggleBotIsAddedToAttachmentMenu.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ToggleBotIsAddedToAttachmentMenu.CONSTRUCTOR);
			output.writeLong(this.botUserId);
			output.writeBoolean(this.isAdded);
			output.writeBoolean(this.allowWriteAccess);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ToggleBotIsAddedToAttachmentMenu toggleBotIsAddedToAttachmentMenu = (ToggleBotIsAddedToAttachmentMenu) o;
			if (this.botUserId != toggleBotIsAddedToAttachmentMenu.botUserId) {
				return false;
			}
			if (this.isAdded != toggleBotIsAddedToAttachmentMenu.isAdded) {
				return false;
			}
			if (this.allowWriteAccess != toggleBotIsAddedToAttachmentMenu.allowWriteAccess) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.botUserId);
			return result;
		}
	}

	/**
	 * Changes active state for a username of a bot. The editable username
	 * can&#039;t be disabled. May return an error with a message
	 * &quot;USERNAMES_ACTIVE_TOO_MUCH&quot; if the maximum number of active
	 * usernames has been reached. Can be called only if
	 * userTypeBot.canBeEdited == true.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ToggleBotUsernameIsActive extends Function<Ok> {


		/**
		 * Identifier of the target bot.
		**/
		public long botUserId;

		/**
		 * The username to change.
		**/
		public String username;

		/**
		 * Pass true to activate the username; pass false to disable it.
		**/
		public boolean isActive;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2036569097;

		/**
		 * Changes active state for a username of a bot. The editable username can&#039;t be disabled. May return an error with a message &quot;USERNAMES_ACTIVE_TOO_MUCH&quot; if the maximum number of active usernames has been reached. Can be called only if userTypeBot.canBeEdited == true.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleBotUsernameIsActive() {}

		/**
		 * Changes active state for a username of a bot. The editable username can&#039;t be disabled. May return an error with a message &quot;USERNAMES_ACTIVE_TOO_MUCH&quot; if the maximum number of active usernames has been reached. Can be called only if userTypeBot.canBeEdited == true.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param botUserId Identifier of the target bot.
		 * @param username The username to change.
		 * @param isActive Pass true to activate the username; pass false to disable it.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleBotUsernameIsActive(long botUserId, String username, boolean isActive) {
			this.botUserId = botUserId;
			this.username = username;
			this.isActive = isActive;
		}

		/**
		 * Changes active state for a username of a bot. The editable username can&#039;t be disabled. May return an error with a message &quot;USERNAMES_ACTIVE_TOO_MUCH&quot; if the maximum number of active usernames has been reached. Can be called only if userTypeBot.canBeEdited == true.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ToggleBotUsernameIsActive(DataInput input) throws IOException {
			this.botUserId = input.readLong();
			if (input.readBoolean()) {
				byte[] usernameTmp = new byte[input.readInt()];
				input.readFully(usernameTmp);
				this.username = new String(usernameTmp, StandardCharsets.UTF_8);
			}
			this.isActive = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ToggleBotUsernameIsActive.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ToggleBotUsernameIsActive.CONSTRUCTOR);
			output.writeLong(this.botUserId);
			if (this.username == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] usernameTmp = this.username.getBytes(StandardCharsets.UTF_8);
				output.writeInt(usernameTmp.length);
				output.write(usernameTmp);
			}
			output.writeBoolean(this.isActive);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ToggleBotUsernameIsActive toggleBotUsernameIsActive = (ToggleBotUsernameIsActive) o;
			if (this.botUserId != toggleBotUsernameIsActive.botUserId) {
				return false;
			}
			if (this.username != toggleBotUsernameIsActive.username) {
				return false;
			}
			if (this.isActive != toggleBotUsernameIsActive.isActive) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.botUserId);
			result = result * 31 + (this.username == null ? 0 : this.username.hashCode());
			return result;
		}
	}

	/**
	 * Changes the value of the default disableNotification parameter, used
	 * when a message is sent to a chat.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ToggleChatDefaultDisableNotification extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * New value of defaultDisableNotification.
		**/
		public boolean defaultDisableNotification;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 314794002;

		/**
		 * Changes the value of the default disableNotification parameter, used when a message is sent to a chat.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleChatDefaultDisableNotification() {}

		/**
		 * Changes the value of the default disableNotification parameter, used when a message is sent to a chat.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param defaultDisableNotification New value of defaultDisableNotification.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleChatDefaultDisableNotification(long chatId, boolean defaultDisableNotification) {
			this.chatId = chatId;
			this.defaultDisableNotification = defaultDisableNotification;
		}

		/**
		 * Changes the value of the default disableNotification parameter, used when a message is sent to a chat.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ToggleChatDefaultDisableNotification(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.defaultDisableNotification = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ToggleChatDefaultDisableNotification.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ToggleChatDefaultDisableNotification.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeBoolean(this.defaultDisableNotification);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ToggleChatDefaultDisableNotification toggleChatDefaultDisableNotification = (ToggleChatDefaultDisableNotification) o;
			if (this.chatId != toggleChatDefaultDisableNotification.chatId) {
				return false;
			}
			if (this.defaultDisableNotification != toggleChatDefaultDisableNotification.defaultDisableNotification) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Changes the ability of users to save, forward, or copy chat content.
	 * Supported only for basic groups, supergroups and channels. Requires
	 * owner privileges.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ToggleChatHasProtectedContent extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * New value of hasProtectedContent.
		**/
		public boolean hasProtectedContent;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 975231309;

		/**
		 * Changes the ability of users to save, forward, or copy chat content. Supported only for basic groups, supergroups and channels. Requires owner privileges.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleChatHasProtectedContent() {}

		/**
		 * Changes the ability of users to save, forward, or copy chat content. Supported only for basic groups, supergroups and channels. Requires owner privileges.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param hasProtectedContent New value of hasProtectedContent.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleChatHasProtectedContent(long chatId, boolean hasProtectedContent) {
			this.chatId = chatId;
			this.hasProtectedContent = hasProtectedContent;
		}

		/**
		 * Changes the ability of users to save, forward, or copy chat content. Supported only for basic groups, supergroups and channels. Requires owner privileges.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ToggleChatHasProtectedContent(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.hasProtectedContent = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ToggleChatHasProtectedContent.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ToggleChatHasProtectedContent.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeBoolean(this.hasProtectedContent);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ToggleChatHasProtectedContent toggleChatHasProtectedContent = (ToggleChatHasProtectedContent) o;
			if (this.chatId != toggleChatHasProtectedContent.chatId) {
				return false;
			}
			if (this.hasProtectedContent != toggleChatHasProtectedContent.hasProtectedContent) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Changes the marked as unread state of a chat.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ToggleChatIsMarkedAsUnread extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * New value of isMarkedAsUnread.
		**/
		public boolean isMarkedAsUnread;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -986129697;

		/**
		 * Changes the marked as unread state of a chat.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleChatIsMarkedAsUnread() {}

		/**
		 * Changes the marked as unread state of a chat.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param isMarkedAsUnread New value of isMarkedAsUnread.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleChatIsMarkedAsUnread(long chatId, boolean isMarkedAsUnread) {
			this.chatId = chatId;
			this.isMarkedAsUnread = isMarkedAsUnread;
		}

		/**
		 * Changes the marked as unread state of a chat.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ToggleChatIsMarkedAsUnread(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.isMarkedAsUnread = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ToggleChatIsMarkedAsUnread.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ToggleChatIsMarkedAsUnread.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeBoolean(this.isMarkedAsUnread);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ToggleChatIsMarkedAsUnread toggleChatIsMarkedAsUnread = (ToggleChatIsMarkedAsUnread) o;
			if (this.chatId != toggleChatIsMarkedAsUnread.chatId) {
				return false;
			}
			if (this.isMarkedAsUnread != toggleChatIsMarkedAsUnread.isMarkedAsUnread) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Changes the pinned state of a chat. There can be up to
	 * getOption(&quot;pinned_chat_count_max&quot;)/getOption(&quot;pinned_archived_chat_count_max&quot;)
	 * pinned non-secret chats and the same number of secret chats in the
	 * main/archive chat list. The limit can be increased with Telegram
	 * Premium.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ToggleChatIsPinned extends Function<Ok> {


		/**
		 * Chat list in which to change the pinned state of the chat.
		**/
		public ChatList chatList;

		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Pass true to pin the chat; pass false to unpin it.
		**/
		public boolean isPinned;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1485429186;

		/**
		 * Changes the pinned state of a chat. There can be up to getOption(&quot;pinned_chat_count_max&quot;)/getOption(&quot;pinned_archived_chat_count_max&quot;) pinned non-secret chats and the same number of secret chats in the main/archive chat list. The limit can be increased with Telegram Premium.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleChatIsPinned() {}

		/**
		 * Changes the pinned state of a chat. There can be up to getOption(&quot;pinned_chat_count_max&quot;)/getOption(&quot;pinned_archived_chat_count_max&quot;) pinned non-secret chats and the same number of secret chats in the main/archive chat list. The limit can be increased with Telegram Premium.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatList Chat list in which to change the pinned state of the chat.
		 * @param chatId Chat identifier.
		 * @param isPinned Pass true to pin the chat; pass false to unpin it.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleChatIsPinned(ChatList chatList, long chatId, boolean isPinned) {
			this.chatList = chatList;
			this.chatId = chatId;
			this.isPinned = isPinned;
		}

		/**
		 * Changes the pinned state of a chat. There can be up to getOption(&quot;pinned_chat_count_max&quot;)/getOption(&quot;pinned_archived_chat_count_max&quot;) pinned non-secret chats and the same number of secret chats in the main/archive chat list. The limit can be increased with Telegram Premium.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ToggleChatIsPinned(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case ChatListMain.CONSTRUCTOR: this.chatList = new ChatListMain(input); break;
					case ChatListArchive.CONSTRUCTOR: this.chatList = new ChatListArchive(input); break;
					case ChatListFolder.CONSTRUCTOR: this.chatList = new ChatListFolder(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.chatId = input.readLong();
			this.isPinned = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ToggleChatIsPinned.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ToggleChatIsPinned.CONSTRUCTOR);
			if (this.chatList == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.chatList.serialize(output);
			}
			output.writeLong(this.chatId);
			output.writeBoolean(this.isPinned);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ToggleChatIsPinned toggleChatIsPinned = (ToggleChatIsPinned) o;
			if (!Objects.equals(this.chatList, toggleChatIsPinned.chatList)) {
				return false;
			}
			if (this.chatId != toggleChatIsPinned.chatId) {
				return false;
			}
			if (this.isPinned != toggleChatIsPinned.isPinned) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.chatList == null ? 0 : this.chatList.hashCode());
			return result;
		}
	}

	/**
	 * Changes the translatable state of a chat; for Telegram Premium users
	 * only.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ToggleChatIsTranslatable extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * New value of isTranslatable.
		**/
		public boolean isTranslatable;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1812345889;

		/**
		 * Changes the translatable state of a chat; for Telegram Premium users only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleChatIsTranslatable() {}

		/**
		 * Changes the translatable state of a chat; for Telegram Premium users only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param isTranslatable New value of isTranslatable.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleChatIsTranslatable(long chatId, boolean isTranslatable) {
			this.chatId = chatId;
			this.isTranslatable = isTranslatable;
		}

		/**
		 * Changes the translatable state of a chat; for Telegram Premium users only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ToggleChatIsTranslatable(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.isTranslatable = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ToggleChatIsTranslatable.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ToggleChatIsTranslatable.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeBoolean(this.isTranslatable);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ToggleChatIsTranslatable toggleChatIsTranslatable = (ToggleChatIsTranslatable) o;
			if (this.chatId != toggleChatIsTranslatable.chatId) {
				return false;
			}
			if (this.isTranslatable != toggleChatIsTranslatable.isTranslatable) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Changes pause state of a file in the file download list.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ToggleDownloadIsPaused extends Function<Ok> {


		/**
		 * Identifier of the downloaded file.
		**/
		public int fileId;

		/**
		 * Pass true if the download is paused.
		**/
		public boolean isPaused;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -947493099;

		/**
		 * Changes pause state of a file in the file download list.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleDownloadIsPaused() {}

		/**
		 * Changes pause state of a file in the file download list.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param fileId Identifier of the downloaded file.
		 * @param isPaused Pass true if the download is paused.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleDownloadIsPaused(int fileId, boolean isPaused) {
			this.fileId = fileId;
			this.isPaused = isPaused;
		}

		/**
		 * Changes pause state of a file in the file download list.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ToggleDownloadIsPaused(DataInput input) throws IOException {
			this.fileId = input.readInt();
			this.isPaused = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ToggleDownloadIsPaused.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ToggleDownloadIsPaused.CONSTRUCTOR);
			output.writeInt(this.fileId);
			output.writeBoolean(this.isPaused);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ToggleDownloadIsPaused toggleDownloadIsPaused = (ToggleDownloadIsPaused) o;
			if (this.fileId != toggleDownloadIsPaused.fileId) {
				return false;
			}
			if (this.isPaused != toggleDownloadIsPaused.isPaused) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.fileId);
			return result;
		}
	}

	/**
	 * Toggles whether a topic is closed in a forum supergroup chat;
	 * requires canManageTopics administrator right in the supergroup unless
	 * the user is creator of the topic.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ToggleForumTopicIsClosed extends Function<Ok> {


		/**
		 * Identifier of the chat.
		**/
		public long chatId;

		/**
		 * Message thread identifier of the forum topic.
		**/
		public long messageThreadId;

		/**
		 * Pass true to close the topic; pass false to reopen it.
		**/
		public boolean isClosed;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -949712141;

		/**
		 * Toggles whether a topic is closed in a forum supergroup chat; requires canManageTopics administrator right in the supergroup unless the user is creator of the topic.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleForumTopicIsClosed() {}

		/**
		 * Toggles whether a topic is closed in a forum supergroup chat; requires canManageTopics administrator right in the supergroup unless the user is creator of the topic.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Identifier of the chat.
		 * @param messageThreadId Message thread identifier of the forum topic.
		 * @param isClosed Pass true to close the topic; pass false to reopen it.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleForumTopicIsClosed(long chatId, long messageThreadId, boolean isClosed) {
			this.chatId = chatId;
			this.messageThreadId = messageThreadId;
			this.isClosed = isClosed;
		}

		/**
		 * Toggles whether a topic is closed in a forum supergroup chat; requires canManageTopics administrator right in the supergroup unless the user is creator of the topic.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ToggleForumTopicIsClosed(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageThreadId = input.readLong();
			this.isClosed = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ToggleForumTopicIsClosed.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ToggleForumTopicIsClosed.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageThreadId);
			output.writeBoolean(this.isClosed);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ToggleForumTopicIsClosed toggleForumTopicIsClosed = (ToggleForumTopicIsClosed) o;
			if (this.chatId != toggleForumTopicIsClosed.chatId) {
				return false;
			}
			if (this.messageThreadId != toggleForumTopicIsClosed.messageThreadId) {
				return false;
			}
			if (this.isClosed != toggleForumTopicIsClosed.isClosed) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Changes the pinned state of a forum topic; requires canManageTopics
	 * administrator right in the supergroup. There can be up to
	 * getOption(&quot;pinned_forum_topic_count_max&quot;) pinned forum
	 * topics.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ToggleForumTopicIsPinned extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Message thread identifier of the forum topic.
		**/
		public long messageThreadId;

		/**
		 * Pass true to pin the topic; pass false to unpin it.
		**/
		public boolean isPinned;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1181543092;

		/**
		 * Changes the pinned state of a forum topic; requires canManageTopics administrator right in the supergroup. There can be up to getOption(&quot;pinned_forum_topic_count_max&quot;) pinned forum topics.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleForumTopicIsPinned() {}

		/**
		 * Changes the pinned state of a forum topic; requires canManageTopics administrator right in the supergroup. There can be up to getOption(&quot;pinned_forum_topic_count_max&quot;) pinned forum topics.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param messageThreadId Message thread identifier of the forum topic.
		 * @param isPinned Pass true to pin the topic; pass false to unpin it.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleForumTopicIsPinned(long chatId, long messageThreadId, boolean isPinned) {
			this.chatId = chatId;
			this.messageThreadId = messageThreadId;
			this.isPinned = isPinned;
		}

		/**
		 * Changes the pinned state of a forum topic; requires canManageTopics administrator right in the supergroup. There can be up to getOption(&quot;pinned_forum_topic_count_max&quot;) pinned forum topics.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ToggleForumTopicIsPinned(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageThreadId = input.readLong();
			this.isPinned = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ToggleForumTopicIsPinned.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ToggleForumTopicIsPinned.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageThreadId);
			output.writeBoolean(this.isPinned);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ToggleForumTopicIsPinned toggleForumTopicIsPinned = (ToggleForumTopicIsPinned) o;
			if (this.chatId != toggleForumTopicIsPinned.chatId) {
				return false;
			}
			if (this.messageThreadId != toggleForumTopicIsPinned.messageThreadId) {
				return false;
			}
			if (this.isPinned != toggleForumTopicIsPinned.isPinned) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Toggles whether a General topic is hidden in a forum supergroup chat;
	 * requires canManageTopics administrator right in the supergroup.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ToggleGeneralForumTopicIsHidden extends Function<Ok> {


		/**
		 * Identifier of the chat.
		**/
		public long chatId;

		/**
		 * Pass true to hide and close the General topic; pass false to unhide it.
		**/
		public boolean isHidden;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1595741256;

		/**
		 * Toggles whether a General topic is hidden in a forum supergroup chat; requires canManageTopics administrator right in the supergroup.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleGeneralForumTopicIsHidden() {}

		/**
		 * Toggles whether a General topic is hidden in a forum supergroup chat; requires canManageTopics administrator right in the supergroup.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Identifier of the chat.
		 * @param isHidden Pass true to hide and close the General topic; pass false to unhide it.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleGeneralForumTopicIsHidden(long chatId, boolean isHidden) {
			this.chatId = chatId;
			this.isHidden = isHidden;
		}

		/**
		 * Toggles whether a General topic is hidden in a forum supergroup chat; requires canManageTopics administrator right in the supergroup.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ToggleGeneralForumTopicIsHidden(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.isHidden = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ToggleGeneralForumTopicIsHidden.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ToggleGeneralForumTopicIsHidden.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeBoolean(this.isHidden);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ToggleGeneralForumTopicIsHidden toggleGeneralForumTopicIsHidden = (ToggleGeneralForumTopicIsHidden) o;
			if (this.chatId != toggleGeneralForumTopicIsHidden.chatId) {
				return false;
			}
			if (this.isHidden != toggleGeneralForumTopicIsHidden.isHidden) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Toggles whether the current user will receive a notification when the
	 * group call will start; scheduled group calls only.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ToggleGroupCallEnabledStartNotification extends Function<Ok> {


		/**
		 * Group call identifier.
		**/
		public int groupCallId;

		/**
		 * New value of the enabledStartNotification setting.
		**/
		public boolean enabledStartNotification;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 707839826;

		/**
		 * Toggles whether the current user will receive a notification when the group call will start; scheduled group calls only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleGroupCallEnabledStartNotification() {}

		/**
		 * Toggles whether the current user will receive a notification when the group call will start; scheduled group calls only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param groupCallId Group call identifier.
		 * @param enabledStartNotification New value of the enabledStartNotification setting.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleGroupCallEnabledStartNotification(int groupCallId, boolean enabledStartNotification) {
			this.groupCallId = groupCallId;
			this.enabledStartNotification = enabledStartNotification;
		}

		/**
		 * Toggles whether the current user will receive a notification when the group call will start; scheduled group calls only.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ToggleGroupCallEnabledStartNotification(DataInput input) throws IOException {
			this.groupCallId = input.readInt();
			this.enabledStartNotification = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ToggleGroupCallEnabledStartNotification.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ToggleGroupCallEnabledStartNotification.CONSTRUCTOR);
			output.writeInt(this.groupCallId);
			output.writeBoolean(this.enabledStartNotification);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ToggleGroupCallEnabledStartNotification toggleGroupCallEnabledStartNotification = (ToggleGroupCallEnabledStartNotification) o;
			if (this.groupCallId != toggleGroupCallEnabledStartNotification.groupCallId) {
				return false;
			}
			if (this.enabledStartNotification != toggleGroupCallEnabledStartNotification.enabledStartNotification) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.groupCallId);
			return result;
		}
	}

	/**
	 * Toggles whether current user&#039;s video is enabled.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ToggleGroupCallIsMyVideoEnabled extends Function<Ok> {


		/**
		 * Group call identifier.
		**/
		public int groupCallId;

		/**
		 * Pass true if the current user&#039;s video is enabled.
		**/
		public boolean isMyVideoEnabled;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1624289030;

		/**
		 * Toggles whether current user&#039;s video is enabled.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleGroupCallIsMyVideoEnabled() {}

		/**
		 * Toggles whether current user&#039;s video is enabled.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param groupCallId Group call identifier.
		 * @param isMyVideoEnabled Pass true if the current user&#039;s video is enabled.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleGroupCallIsMyVideoEnabled(int groupCallId, boolean isMyVideoEnabled) {
			this.groupCallId = groupCallId;
			this.isMyVideoEnabled = isMyVideoEnabled;
		}

		/**
		 * Toggles whether current user&#039;s video is enabled.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ToggleGroupCallIsMyVideoEnabled(DataInput input) throws IOException {
			this.groupCallId = input.readInt();
			this.isMyVideoEnabled = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ToggleGroupCallIsMyVideoEnabled.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ToggleGroupCallIsMyVideoEnabled.CONSTRUCTOR);
			output.writeInt(this.groupCallId);
			output.writeBoolean(this.isMyVideoEnabled);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ToggleGroupCallIsMyVideoEnabled toggleGroupCallIsMyVideoEnabled = (ToggleGroupCallIsMyVideoEnabled) o;
			if (this.groupCallId != toggleGroupCallIsMyVideoEnabled.groupCallId) {
				return false;
			}
			if (this.isMyVideoEnabled != toggleGroupCallIsMyVideoEnabled.isMyVideoEnabled) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.groupCallId);
			return result;
		}
	}

	/**
	 * Toggles whether current user&#039;s video is paused.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ToggleGroupCallIsMyVideoPaused extends Function<Ok> {


		/**
		 * Group call identifier.
		**/
		public int groupCallId;

		/**
		 * Pass true if the current user&#039;s video is paused.
		**/
		public boolean isMyVideoPaused;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -478875239;

		/**
		 * Toggles whether current user&#039;s video is paused.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleGroupCallIsMyVideoPaused() {}

		/**
		 * Toggles whether current user&#039;s video is paused.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param groupCallId Group call identifier.
		 * @param isMyVideoPaused Pass true if the current user&#039;s video is paused.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleGroupCallIsMyVideoPaused(int groupCallId, boolean isMyVideoPaused) {
			this.groupCallId = groupCallId;
			this.isMyVideoPaused = isMyVideoPaused;
		}

		/**
		 * Toggles whether current user&#039;s video is paused.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ToggleGroupCallIsMyVideoPaused(DataInput input) throws IOException {
			this.groupCallId = input.readInt();
			this.isMyVideoPaused = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ToggleGroupCallIsMyVideoPaused.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ToggleGroupCallIsMyVideoPaused.CONSTRUCTOR);
			output.writeInt(this.groupCallId);
			output.writeBoolean(this.isMyVideoPaused);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ToggleGroupCallIsMyVideoPaused toggleGroupCallIsMyVideoPaused = (ToggleGroupCallIsMyVideoPaused) o;
			if (this.groupCallId != toggleGroupCallIsMyVideoPaused.groupCallId) {
				return false;
			}
			if (this.isMyVideoPaused != toggleGroupCallIsMyVideoPaused.isMyVideoPaused) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.groupCallId);
			return result;
		}
	}

	/**
	 * Toggles whether new participants of a group call can be unmuted only
	 * by administrators of the group call. Requires
	 * groupCall.canToggleMuteNewParticipants group call flag.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ToggleGroupCallMuteNewParticipants extends Function<Ok> {


		/**
		 * Group call identifier.
		**/
		public int groupCallId;

		/**
		 * New value of the muteNewParticipants setting.
		**/
		public boolean muteNewParticipants;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 284082626;

		/**
		 * Toggles whether new participants of a group call can be unmuted only by administrators of the group call. Requires groupCall.canToggleMuteNewParticipants group call flag.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleGroupCallMuteNewParticipants() {}

		/**
		 * Toggles whether new participants of a group call can be unmuted only by administrators of the group call. Requires groupCall.canToggleMuteNewParticipants group call flag.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param groupCallId Group call identifier.
		 * @param muteNewParticipants New value of the muteNewParticipants setting.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleGroupCallMuteNewParticipants(int groupCallId, boolean muteNewParticipants) {
			this.groupCallId = groupCallId;
			this.muteNewParticipants = muteNewParticipants;
		}

		/**
		 * Toggles whether new participants of a group call can be unmuted only by administrators of the group call. Requires groupCall.canToggleMuteNewParticipants group call flag.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ToggleGroupCallMuteNewParticipants(DataInput input) throws IOException {
			this.groupCallId = input.readInt();
			this.muteNewParticipants = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ToggleGroupCallMuteNewParticipants.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ToggleGroupCallMuteNewParticipants.CONSTRUCTOR);
			output.writeInt(this.groupCallId);
			output.writeBoolean(this.muteNewParticipants);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ToggleGroupCallMuteNewParticipants toggleGroupCallMuteNewParticipants = (ToggleGroupCallMuteNewParticipants) o;
			if (this.groupCallId != toggleGroupCallMuteNewParticipants.groupCallId) {
				return false;
			}
			if (this.muteNewParticipants != toggleGroupCallMuteNewParticipants.muteNewParticipants) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.groupCallId);
			return result;
		}
	}

	/**
	 * Toggles whether a group call participant hand is rased.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ToggleGroupCallParticipantIsHandRaised extends Function<Ok> {


		/**
		 * Group call identifier.
		**/
		public int groupCallId;

		/**
		 * Participant identifier.
		**/
		public MessageSender participantId;

		/**
		 * Pass true if the user&#039;s hand needs to be raised. Only self hand can be raised. Requires groupCall.canBeManaged group call flag to lower other&#039;s hand.
		**/
		public boolean isHandRaised;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1896127519;

		/**
		 * Toggles whether a group call participant hand is rased.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleGroupCallParticipantIsHandRaised() {}

		/**
		 * Toggles whether a group call participant hand is rased.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param groupCallId Group call identifier.
		 * @param participantId Participant identifier.
		 * @param isHandRaised Pass true if the user&#039;s hand needs to be raised. Only self hand can be raised. Requires groupCall.canBeManaged group call flag to lower other&#039;s hand.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleGroupCallParticipantIsHandRaised(int groupCallId,
				MessageSender participantId,
				boolean isHandRaised) {
			this.groupCallId = groupCallId;
			this.participantId = participantId;
			this.isHandRaised = isHandRaised;
		}

		/**
		 * Toggles whether a group call participant hand is rased.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ToggleGroupCallParticipantIsHandRaised(DataInput input) throws IOException {
			this.groupCallId = input.readInt();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case MessageSenderUser.CONSTRUCTOR: this.participantId = new MessageSenderUser(input); break;
					case MessageSenderChat.CONSTRUCTOR: this.participantId = new MessageSenderChat(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.isHandRaised = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ToggleGroupCallParticipantIsHandRaised.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ToggleGroupCallParticipantIsHandRaised.CONSTRUCTOR);
			output.writeInt(this.groupCallId);
			if (this.participantId == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.participantId.serialize(output);
			}
			output.writeBoolean(this.isHandRaised);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ToggleGroupCallParticipantIsHandRaised toggleGroupCallParticipantIsHandRaised = (ToggleGroupCallParticipantIsHandRaised) o;
			if (this.groupCallId != toggleGroupCallParticipantIsHandRaised.groupCallId) {
				return false;
			}
			if (!Objects.equals(this.participantId, toggleGroupCallParticipantIsHandRaised.participantId)) {
				return false;
			}
			if (this.isHandRaised != toggleGroupCallParticipantIsHandRaised.isHandRaised) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.groupCallId);
			result = result * 31 + (this.participantId == null ? 0 : this.participantId.hashCode());
			return result;
		}
	}

	/**
	 * Toggles whether a participant of an active group call is muted,
	 * unmuted, or allowed to unmute themselves.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ToggleGroupCallParticipantIsMuted extends Function<Ok> {


		/**
		 * Group call identifier.
		**/
		public int groupCallId;

		/**
		 * Participant identifier.
		**/
		public MessageSender participantId;

		/**
		 * Pass true to mute the user; pass false to unmute the them.
		**/
		public boolean isMuted;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1308093433;

		/**
		 * Toggles whether a participant of an active group call is muted, unmuted, or allowed to unmute themselves.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleGroupCallParticipantIsMuted() {}

		/**
		 * Toggles whether a participant of an active group call is muted, unmuted, or allowed to unmute themselves.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param groupCallId Group call identifier.
		 * @param participantId Participant identifier.
		 * @param isMuted Pass true to mute the user; pass false to unmute the them.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleGroupCallParticipantIsMuted(int groupCallId,
				MessageSender participantId,
				boolean isMuted) {
			this.groupCallId = groupCallId;
			this.participantId = participantId;
			this.isMuted = isMuted;
		}

		/**
		 * Toggles whether a participant of an active group call is muted, unmuted, or allowed to unmute themselves.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ToggleGroupCallParticipantIsMuted(DataInput input) throws IOException {
			this.groupCallId = input.readInt();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case MessageSenderUser.CONSTRUCTOR: this.participantId = new MessageSenderUser(input); break;
					case MessageSenderChat.CONSTRUCTOR: this.participantId = new MessageSenderChat(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.isMuted = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ToggleGroupCallParticipantIsMuted.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ToggleGroupCallParticipantIsMuted.CONSTRUCTOR);
			output.writeInt(this.groupCallId);
			if (this.participantId == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.participantId.serialize(output);
			}
			output.writeBoolean(this.isMuted);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ToggleGroupCallParticipantIsMuted toggleGroupCallParticipantIsMuted = (ToggleGroupCallParticipantIsMuted) o;
			if (this.groupCallId != toggleGroupCallParticipantIsMuted.groupCallId) {
				return false;
			}
			if (!Objects.equals(this.participantId, toggleGroupCallParticipantIsMuted.participantId)) {
				return false;
			}
			if (this.isMuted != toggleGroupCallParticipantIsMuted.isMuted) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.groupCallId);
			result = result * 31 + (this.participantId == null ? 0 : this.participantId.hashCode());
			return result;
		}
	}

	/**
	 * Pauses or unpauses screen sharing in a joined group call.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ToggleGroupCallScreenSharingIsPaused extends Function<Ok> {


		/**
		 * Group call identifier.
		**/
		public int groupCallId;

		/**
		 * Pass true to pause screen sharing; pass false to unpause it.
		**/
		public boolean isPaused;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1602530464;

		/**
		 * Pauses or unpauses screen sharing in a joined group call.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleGroupCallScreenSharingIsPaused() {}

		/**
		 * Pauses or unpauses screen sharing in a joined group call.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param groupCallId Group call identifier.
		 * @param isPaused Pass true to pause screen sharing; pass false to unpause it.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleGroupCallScreenSharingIsPaused(int groupCallId, boolean isPaused) {
			this.groupCallId = groupCallId;
			this.isPaused = isPaused;
		}

		/**
		 * Pauses or unpauses screen sharing in a joined group call.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ToggleGroupCallScreenSharingIsPaused(DataInput input) throws IOException {
			this.groupCallId = input.readInt();
			this.isPaused = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ToggleGroupCallScreenSharingIsPaused.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ToggleGroupCallScreenSharingIsPaused.CONSTRUCTOR);
			output.writeInt(this.groupCallId);
			output.writeBoolean(this.isPaused);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ToggleGroupCallScreenSharingIsPaused toggleGroupCallScreenSharingIsPaused = (ToggleGroupCallScreenSharingIsPaused) o;
			if (this.groupCallId != toggleGroupCallScreenSharingIsPaused.groupCallId) {
				return false;
			}
			if (this.isPaused != toggleGroupCallScreenSharingIsPaused.isPaused) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Integer.hashCode(this.groupCallId);
			return result;
		}
	}

	/**
	 * Changes the block state of a message sender. Currently, only users
	 * and supergroup chats can be blocked.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ToggleMessageSenderIsBlocked extends Function<Ok> {


		/**
		 * Identifier of a message sender to block/unblock.
		**/
		public MessageSender senderId;

		/**
		 * New value of isBlocked.
		**/
		public boolean isBlocked;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -2008084779;

		/**
		 * Changes the block state of a message sender. Currently, only users and supergroup chats can be blocked.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleMessageSenderIsBlocked() {}

		/**
		 * Changes the block state of a message sender. Currently, only users and supergroup chats can be blocked.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param senderId Identifier of a message sender to block/unblock.
		 * @param isBlocked New value of isBlocked.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleMessageSenderIsBlocked(MessageSender senderId, boolean isBlocked) {
			this.senderId = senderId;
			this.isBlocked = isBlocked;
		}

		/**
		 * Changes the block state of a message sender. Currently, only users and supergroup chats can be blocked.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ToggleMessageSenderIsBlocked(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case MessageSenderUser.CONSTRUCTOR: this.senderId = new MessageSenderUser(input); break;
					case MessageSenderChat.CONSTRUCTOR: this.senderId = new MessageSenderChat(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.isBlocked = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ToggleMessageSenderIsBlocked.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ToggleMessageSenderIsBlocked.CONSTRUCTOR);
			if (this.senderId == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.senderId.serialize(output);
			}
			output.writeBoolean(this.isBlocked);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ToggleMessageSenderIsBlocked toggleMessageSenderIsBlocked = (ToggleMessageSenderIsBlocked) o;
			if (!Objects.equals(this.senderId, toggleMessageSenderIsBlocked.senderId)) {
				return false;
			}
			if (this.isBlocked != toggleMessageSenderIsBlocked.isBlocked) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isBlocked);
			result = result * 31 + (this.senderId == null ? 0 : this.senderId.hashCode());
			return result;
		}
	}

	/**
	 * Toggles whether a session can accept incoming calls.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ToggleSessionCanAcceptCalls extends Function<Ok> {


		/**
		 * Session identifier.
		**/
		public long sessionId;

		/**
		 * Pass true to allow accepting incoming calls by the session; pass false otherwise.
		**/
		public boolean canAcceptCalls;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1819027208;

		/**
		 * Toggles whether a session can accept incoming calls.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleSessionCanAcceptCalls() {}

		/**
		 * Toggles whether a session can accept incoming calls.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param sessionId Session identifier.
		 * @param canAcceptCalls Pass true to allow accepting incoming calls by the session; pass false otherwise.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleSessionCanAcceptCalls(long sessionId, boolean canAcceptCalls) {
			this.sessionId = sessionId;
			this.canAcceptCalls = canAcceptCalls;
		}

		/**
		 * Toggles whether a session can accept incoming calls.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ToggleSessionCanAcceptCalls(DataInput input) throws IOException {
			this.sessionId = input.readLong();
			this.canAcceptCalls = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ToggleSessionCanAcceptCalls.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ToggleSessionCanAcceptCalls.CONSTRUCTOR);
			output.writeLong(this.sessionId);
			output.writeBoolean(this.canAcceptCalls);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ToggleSessionCanAcceptCalls toggleSessionCanAcceptCalls = (ToggleSessionCanAcceptCalls) o;
			if (this.sessionId != toggleSessionCanAcceptCalls.sessionId) {
				return false;
			}
			if (this.canAcceptCalls != toggleSessionCanAcceptCalls.canAcceptCalls) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.sessionId);
			return result;
		}
	}

	/**
	 * Toggles whether a session can accept incoming secret chats.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ToggleSessionCanAcceptSecretChats extends Function<Ok> {


		/**
		 * Session identifier.
		**/
		public long sessionId;

		/**
		 * Pass true to allow accepting secret chats by the session; pass false otherwise.
		**/
		public boolean canAcceptSecretChats;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1000843390;

		/**
		 * Toggles whether a session can accept incoming secret chats.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleSessionCanAcceptSecretChats() {}

		/**
		 * Toggles whether a session can accept incoming secret chats.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param sessionId Session identifier.
		 * @param canAcceptSecretChats Pass true to allow accepting secret chats by the session; pass false otherwise.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleSessionCanAcceptSecretChats(long sessionId, boolean canAcceptSecretChats) {
			this.sessionId = sessionId;
			this.canAcceptSecretChats = canAcceptSecretChats;
		}

		/**
		 * Toggles whether a session can accept incoming secret chats.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ToggleSessionCanAcceptSecretChats(DataInput input) throws IOException {
			this.sessionId = input.readLong();
			this.canAcceptSecretChats = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ToggleSessionCanAcceptSecretChats.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ToggleSessionCanAcceptSecretChats.CONSTRUCTOR);
			output.writeLong(this.sessionId);
			output.writeBoolean(this.canAcceptSecretChats);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ToggleSessionCanAcceptSecretChats toggleSessionCanAcceptSecretChats = (ToggleSessionCanAcceptSecretChats) o;
			if (this.sessionId != toggleSessionCanAcceptSecretChats.sessionId) {
				return false;
			}
			if (this.canAcceptSecretChats != toggleSessionCanAcceptSecretChats.canAcceptSecretChats) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.sessionId);
			return result;
		}
	}

	/**
	 * Toggles whether aggressive anti-spam checks are enabled in the
	 * supergroup. Can be called only if
	 * supergroupFullInfo.canToggleAggressiveAntiSpam == true.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ToggleSupergroupHasAggressiveAntiSpamEnabled extends Function<Ok> {


		/**
		 * The identifier of the supergroup, which isn&#039;t a broadcast group.
		**/
		public long supergroupId;

		/**
		 * The new value of hasAggressiveAntiSpamEnabled.
		**/
		public boolean hasAggressiveAntiSpamEnabled;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1748956943;

		/**
		 * Toggles whether aggressive anti-spam checks are enabled in the supergroup. Can be called only if supergroupFullInfo.canToggleAggressiveAntiSpam == true.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleSupergroupHasAggressiveAntiSpamEnabled() {}

		/**
		 * Toggles whether aggressive anti-spam checks are enabled in the supergroup. Can be called only if supergroupFullInfo.canToggleAggressiveAntiSpam == true.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param supergroupId The identifier of the supergroup, which isn&#039;t a broadcast group.
		 * @param hasAggressiveAntiSpamEnabled The new value of hasAggressiveAntiSpamEnabled.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleSupergroupHasAggressiveAntiSpamEnabled(long supergroupId, boolean hasAggressiveAntiSpamEnabled) {
			this.supergroupId = supergroupId;
			this.hasAggressiveAntiSpamEnabled = hasAggressiveAntiSpamEnabled;
		}

		/**
		 * Toggles whether aggressive anti-spam checks are enabled in the supergroup. Can be called only if supergroupFullInfo.canToggleAggressiveAntiSpam == true.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ToggleSupergroupHasAggressiveAntiSpamEnabled(DataInput input) throws IOException {
			this.supergroupId = input.readLong();
			this.hasAggressiveAntiSpamEnabled = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ToggleSupergroupHasAggressiveAntiSpamEnabled.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ToggleSupergroupHasAggressiveAntiSpamEnabled.CONSTRUCTOR);
			output.writeLong(this.supergroupId);
			output.writeBoolean(this.hasAggressiveAntiSpamEnabled);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ToggleSupergroupHasAggressiveAntiSpamEnabled toggleSupergroupHasAggressiveAntiSpamEnabled = (ToggleSupergroupHasAggressiveAntiSpamEnabled) o;
			if (this.supergroupId != toggleSupergroupHasAggressiveAntiSpamEnabled.supergroupId) {
				return false;
			}
			if (this.hasAggressiveAntiSpamEnabled != toggleSupergroupHasAggressiveAntiSpamEnabled.hasAggressiveAntiSpamEnabled) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.supergroupId);
			return result;
		}
	}

	/**
	 * Toggles whether non-administrators can receive only administrators
	 * and bots using getSupergroupMembers or searchChatMembers. Can be
	 * called only if supergroupFullInfo.canHideMembers == true.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ToggleSupergroupHasHiddenMembers extends Function<Ok> {


		/**
		 * Identifier of the supergroup.
		**/
		public long supergroupId;

		/**
		 * New value of hasHiddenMembers.
		**/
		public boolean hasHiddenMembers;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1537892918;

		/**
		 * Toggles whether non-administrators can receive only administrators and bots using getSupergroupMembers or searchChatMembers. Can be called only if supergroupFullInfo.canHideMembers == true.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleSupergroupHasHiddenMembers() {}

		/**
		 * Toggles whether non-administrators can receive only administrators and bots using getSupergroupMembers or searchChatMembers. Can be called only if supergroupFullInfo.canHideMembers == true.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param supergroupId Identifier of the supergroup.
		 * @param hasHiddenMembers New value of hasHiddenMembers.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleSupergroupHasHiddenMembers(long supergroupId, boolean hasHiddenMembers) {
			this.supergroupId = supergroupId;
			this.hasHiddenMembers = hasHiddenMembers;
		}

		/**
		 * Toggles whether non-administrators can receive only administrators and bots using getSupergroupMembers or searchChatMembers. Can be called only if supergroupFullInfo.canHideMembers == true.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ToggleSupergroupHasHiddenMembers(DataInput input) throws IOException {
			this.supergroupId = input.readLong();
			this.hasHiddenMembers = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ToggleSupergroupHasHiddenMembers.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ToggleSupergroupHasHiddenMembers.CONSTRUCTOR);
			output.writeLong(this.supergroupId);
			output.writeBoolean(this.hasHiddenMembers);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ToggleSupergroupHasHiddenMembers toggleSupergroupHasHiddenMembers = (ToggleSupergroupHasHiddenMembers) o;
			if (this.supergroupId != toggleSupergroupHasHiddenMembers.supergroupId) {
				return false;
			}
			if (this.hasHiddenMembers != toggleSupergroupHasHiddenMembers.hasHiddenMembers) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.supergroupId);
			return result;
		}
	}

	/**
	 * Toggles whether the message history of a supergroup is available to
	 * new members; requires canChangeInfo administrator right.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ToggleSupergroupIsAllHistoryAvailable extends Function<Ok> {


		/**
		 * The identifier of the supergroup.
		**/
		public long supergroupId;

		/**
		 * The new value of isAllHistoryAvailable.
		**/
		public boolean isAllHistoryAvailable;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1155110478;

		/**
		 * Toggles whether the message history of a supergroup is available to new members; requires canChangeInfo administrator right.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleSupergroupIsAllHistoryAvailable() {}

		/**
		 * Toggles whether the message history of a supergroup is available to new members; requires canChangeInfo administrator right.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param supergroupId The identifier of the supergroup.
		 * @param isAllHistoryAvailable The new value of isAllHistoryAvailable.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleSupergroupIsAllHistoryAvailable(long supergroupId, boolean isAllHistoryAvailable) {
			this.supergroupId = supergroupId;
			this.isAllHistoryAvailable = isAllHistoryAvailable;
		}

		/**
		 * Toggles whether the message history of a supergroup is available to new members; requires canChangeInfo administrator right.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ToggleSupergroupIsAllHistoryAvailable(DataInput input) throws IOException {
			this.supergroupId = input.readLong();
			this.isAllHistoryAvailable = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ToggleSupergroupIsAllHistoryAvailable.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ToggleSupergroupIsAllHistoryAvailable.CONSTRUCTOR);
			output.writeLong(this.supergroupId);
			output.writeBoolean(this.isAllHistoryAvailable);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ToggleSupergroupIsAllHistoryAvailable toggleSupergroupIsAllHistoryAvailable = (ToggleSupergroupIsAllHistoryAvailable) o;
			if (this.supergroupId != toggleSupergroupIsAllHistoryAvailable.supergroupId) {
				return false;
			}
			if (this.isAllHistoryAvailable != toggleSupergroupIsAllHistoryAvailable.isAllHistoryAvailable) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.supergroupId);
			return result;
		}
	}

	/**
	 * Upgrades supergroup to a broadcast group; requires owner privileges
	 * in the supergroup.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ToggleSupergroupIsBroadcastGroup extends Function<Ok> {


		/**
		 * Identifier of the supergroup.
		**/
		public long supergroupId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 884089365;

		/**
		 * Upgrades supergroup to a broadcast group; requires owner privileges in the supergroup.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleSupergroupIsBroadcastGroup() {}

		/**
		 * Upgrades supergroup to a broadcast group; requires owner privileges in the supergroup.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param supergroupId Identifier of the supergroup.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleSupergroupIsBroadcastGroup(long supergroupId) {
			this.supergroupId = supergroupId;
		}

		/**
		 * Upgrades supergroup to a broadcast group; requires owner privileges in the supergroup.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ToggleSupergroupIsBroadcastGroup(DataInput input) throws IOException {
			this.supergroupId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ToggleSupergroupIsBroadcastGroup.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ToggleSupergroupIsBroadcastGroup.CONSTRUCTOR);
			output.writeLong(this.supergroupId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ToggleSupergroupIsBroadcastGroup toggleSupergroupIsBroadcastGroup = (ToggleSupergroupIsBroadcastGroup) o;
			if (this.supergroupId != toggleSupergroupIsBroadcastGroup.supergroupId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.supergroupId);
		}
	}

	/**
	 * Toggles whether the supergroup is a forum; requires owner privileges
	 * in the supergroup. Discussion supergroups can&#039;t be converted to
	 * forums.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ToggleSupergroupIsForum extends Function<Ok> {


		/**
		 * Identifier of the supergroup.
		**/
		public long supergroupId;

		/**
		 * New value of isForum.
		**/
		public boolean isForum;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1771071990;

		/**
		 * Toggles whether the supergroup is a forum; requires owner privileges in the supergroup. Discussion supergroups can&#039;t be converted to forums.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleSupergroupIsForum() {}

		/**
		 * Toggles whether the supergroup is a forum; requires owner privileges in the supergroup. Discussion supergroups can&#039;t be converted to forums.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param supergroupId Identifier of the supergroup.
		 * @param isForum New value of isForum.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleSupergroupIsForum(long supergroupId, boolean isForum) {
			this.supergroupId = supergroupId;
			this.isForum = isForum;
		}

		/**
		 * Toggles whether the supergroup is a forum; requires owner privileges in the supergroup. Discussion supergroups can&#039;t be converted to forums.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ToggleSupergroupIsForum(DataInput input) throws IOException {
			this.supergroupId = input.readLong();
			this.isForum = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ToggleSupergroupIsForum.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ToggleSupergroupIsForum.CONSTRUCTOR);
			output.writeLong(this.supergroupId);
			output.writeBoolean(this.isForum);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ToggleSupergroupIsForum toggleSupergroupIsForum = (ToggleSupergroupIsForum) o;
			if (this.supergroupId != toggleSupergroupIsForum.supergroupId) {
				return false;
			}
			if (this.isForum != toggleSupergroupIsForum.isForum) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.supergroupId);
			return result;
		}
	}

	/**
	 * Toggles whether all users directly joining the supergroup need to be
	 * approved by supergroup administrators; requires canRestrictMembers
	 * administrator right.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ToggleSupergroupJoinByRequest extends Function<Ok> {


		/**
		 * Identifier of the channel.
		**/
		public long supergroupId;

		/**
		 * New value of joinByRequest.
		**/
		public boolean joinByRequest;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2111807454;

		/**
		 * Toggles whether all users directly joining the supergroup need to be approved by supergroup administrators; requires canRestrictMembers administrator right.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleSupergroupJoinByRequest() {}

		/**
		 * Toggles whether all users directly joining the supergroup need to be approved by supergroup administrators; requires canRestrictMembers administrator right.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param supergroupId Identifier of the channel.
		 * @param joinByRequest New value of joinByRequest.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleSupergroupJoinByRequest(long supergroupId, boolean joinByRequest) {
			this.supergroupId = supergroupId;
			this.joinByRequest = joinByRequest;
		}

		/**
		 * Toggles whether all users directly joining the supergroup need to be approved by supergroup administrators; requires canRestrictMembers administrator right.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ToggleSupergroupJoinByRequest(DataInput input) throws IOException {
			this.supergroupId = input.readLong();
			this.joinByRequest = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ToggleSupergroupJoinByRequest.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ToggleSupergroupJoinByRequest.CONSTRUCTOR);
			output.writeLong(this.supergroupId);
			output.writeBoolean(this.joinByRequest);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ToggleSupergroupJoinByRequest toggleSupergroupJoinByRequest = (ToggleSupergroupJoinByRequest) o;
			if (this.supergroupId != toggleSupergroupJoinByRequest.supergroupId) {
				return false;
			}
			if (this.joinByRequest != toggleSupergroupJoinByRequest.joinByRequest) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.supergroupId);
			return result;
		}
	}

	/**
	 * Toggles whether joining is mandatory to send messages to a discussion
	 * supergroup; requires canRestrictMembers administrator right.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ToggleSupergroupJoinToSendMessages extends Function<Ok> {


		/**
		 * Identifier of the supergroup.
		**/
		public long supergroupId;

		/**
		 * New value of joinToSendMessages.
		**/
		public boolean joinToSendMessages;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -182022642;

		/**
		 * Toggles whether joining is mandatory to send messages to a discussion supergroup; requires canRestrictMembers administrator right.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleSupergroupJoinToSendMessages() {}

		/**
		 * Toggles whether joining is mandatory to send messages to a discussion supergroup; requires canRestrictMembers administrator right.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param supergroupId Identifier of the supergroup.
		 * @param joinToSendMessages New value of joinToSendMessages.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleSupergroupJoinToSendMessages(long supergroupId, boolean joinToSendMessages) {
			this.supergroupId = supergroupId;
			this.joinToSendMessages = joinToSendMessages;
		}

		/**
		 * Toggles whether joining is mandatory to send messages to a discussion supergroup; requires canRestrictMembers administrator right.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ToggleSupergroupJoinToSendMessages(DataInput input) throws IOException {
			this.supergroupId = input.readLong();
			this.joinToSendMessages = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ToggleSupergroupJoinToSendMessages.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ToggleSupergroupJoinToSendMessages.CONSTRUCTOR);
			output.writeLong(this.supergroupId);
			output.writeBoolean(this.joinToSendMessages);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ToggleSupergroupJoinToSendMessages toggleSupergroupJoinToSendMessages = (ToggleSupergroupJoinToSendMessages) o;
			if (this.supergroupId != toggleSupergroupJoinToSendMessages.supergroupId) {
				return false;
			}
			if (this.joinToSendMessages != toggleSupergroupJoinToSendMessages.joinToSendMessages) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.supergroupId);
			return result;
		}
	}

	/**
	 * Toggles whether sender signature is added to sent messages in a
	 * channel; requires canChangeInfo administrator right.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ToggleSupergroupSignMessages extends Function<Ok> {


		/**
		 * Identifier of the channel.
		**/
		public long supergroupId;

		/**
		 * New value of signMessages.
		**/
		public boolean signMessages;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1156568356;

		/**
		 * Toggles whether sender signature is added to sent messages in a channel; requires canChangeInfo administrator right.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleSupergroupSignMessages() {}

		/**
		 * Toggles whether sender signature is added to sent messages in a channel; requires canChangeInfo administrator right.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param supergroupId Identifier of the channel.
		 * @param signMessages New value of signMessages.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleSupergroupSignMessages(long supergroupId, boolean signMessages) {
			this.supergroupId = supergroupId;
			this.signMessages = signMessages;
		}

		/**
		 * Toggles whether sender signature is added to sent messages in a channel; requires canChangeInfo administrator right.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ToggleSupergroupSignMessages(DataInput input) throws IOException {
			this.supergroupId = input.readLong();
			this.signMessages = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ToggleSupergroupSignMessages.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ToggleSupergroupSignMessages.CONSTRUCTOR);
			output.writeLong(this.supergroupId);
			output.writeBoolean(this.signMessages);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ToggleSupergroupSignMessages toggleSupergroupSignMessages = (ToggleSupergroupSignMessages) o;
			if (this.supergroupId != toggleSupergroupSignMessages.supergroupId) {
				return false;
			}
			if (this.signMessages != toggleSupergroupSignMessages.signMessages) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.supergroupId);
			return result;
		}
	}

	/**
	 * Changes active state for a username of a supergroup or channel,
	 * requires owner privileges in the supergroup or channel. The editable
	 * username can&#039;t be disabled. May return an error with a message
	 * &quot;USERNAMES_ACTIVE_TOO_MUCH&quot; if the maximum number of active
	 * usernames has been reached.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ToggleSupergroupUsernameIsActive extends Function<Ok> {


		/**
		 * Identifier of the supergroup or channel.
		**/
		public long supergroupId;

		/**
		 * The username to change.
		**/
		public String username;

		/**
		 * Pass true to activate the username; pass false to disable it.
		**/
		public boolean isActive;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1500811777;

		/**
		 * Changes active state for a username of a supergroup or channel, requires owner privileges in the supergroup or channel. The editable username can&#039;t be disabled. May return an error with a message &quot;USERNAMES_ACTIVE_TOO_MUCH&quot; if the maximum number of active usernames has been reached.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleSupergroupUsernameIsActive() {}

		/**
		 * Changes active state for a username of a supergroup or channel, requires owner privileges in the supergroup or channel. The editable username can&#039;t be disabled. May return an error with a message &quot;USERNAMES_ACTIVE_TOO_MUCH&quot; if the maximum number of active usernames has been reached.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param supergroupId Identifier of the supergroup or channel.
		 * @param username The username to change.
		 * @param isActive Pass true to activate the username; pass false to disable it.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleSupergroupUsernameIsActive(long supergroupId, String username, boolean isActive) {
			this.supergroupId = supergroupId;
			this.username = username;
			this.isActive = isActive;
		}

		/**
		 * Changes active state for a username of a supergroup or channel, requires owner privileges in the supergroup or channel. The editable username can&#039;t be disabled. May return an error with a message &quot;USERNAMES_ACTIVE_TOO_MUCH&quot; if the maximum number of active usernames has been reached.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ToggleSupergroupUsernameIsActive(DataInput input) throws IOException {
			this.supergroupId = input.readLong();
			if (input.readBoolean()) {
				byte[] usernameTmp = new byte[input.readInt()];
				input.readFully(usernameTmp);
				this.username = new String(usernameTmp, StandardCharsets.UTF_8);
			}
			this.isActive = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ToggleSupergroupUsernameIsActive.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ToggleSupergroupUsernameIsActive.CONSTRUCTOR);
			output.writeLong(this.supergroupId);
			if (this.username == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] usernameTmp = this.username.getBytes(StandardCharsets.UTF_8);
				output.writeInt(usernameTmp.length);
				output.write(usernameTmp);
			}
			output.writeBoolean(this.isActive);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ToggleSupergroupUsernameIsActive toggleSupergroupUsernameIsActive = (ToggleSupergroupUsernameIsActive) o;
			if (this.supergroupId != toggleSupergroupUsernameIsActive.supergroupId) {
				return false;
			}
			if (this.username != toggleSupergroupUsernameIsActive.username) {
				return false;
			}
			if (this.isActive != toggleSupergroupUsernameIsActive.isActive) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.supergroupId);
			result = result * 31 + (this.username == null ? 0 : this.username.hashCode());
			return result;
		}
	}

	/**
	 * Changes active state for a username of the current user. The editable
	 * username can&#039;t be disabled. May return an error with a message
	 * &quot;USERNAMES_ACTIVE_TOO_MUCH&quot; if the maximum number of active
	 * usernames has been reached.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ToggleUsernameIsActive extends Function<Ok> {


		/**
		 * The username to change.
		**/
		public String username;

		/**
		 * Pass true to activate the username; pass false to disable it.
		**/
		public boolean isActive;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1244098019;

		/**
		 * Changes active state for a username of the current user. The editable username can&#039;t be disabled. May return an error with a message &quot;USERNAMES_ACTIVE_TOO_MUCH&quot; if the maximum number of active usernames has been reached.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleUsernameIsActive() {}

		/**
		 * Changes active state for a username of the current user. The editable username can&#039;t be disabled. May return an error with a message &quot;USERNAMES_ACTIVE_TOO_MUCH&quot; if the maximum number of active usernames has been reached.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param username The username to change.
		 * @param isActive Pass true to activate the username; pass false to disable it.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ToggleUsernameIsActive(String username, boolean isActive) {
			this.username = username;
			this.isActive = isActive;
		}

		/**
		 * Changes active state for a username of the current user. The editable username can&#039;t be disabled. May return an error with a message &quot;USERNAMES_ACTIVE_TOO_MUCH&quot; if the maximum number of active usernames has been reached.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ToggleUsernameIsActive(DataInput input) throws IOException {
			if (input.readBoolean()) {
				byte[] usernameTmp = new byte[input.readInt()];
				input.readFully(usernameTmp);
				this.username = new String(usernameTmp, StandardCharsets.UTF_8);
			}
			this.isActive = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ToggleUsernameIsActive.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ToggleUsernameIsActive.CONSTRUCTOR);
			if (this.username == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] usernameTmp = this.username.getBytes(StandardCharsets.UTF_8);
				output.writeInt(usernameTmp.length);
				output.write(usernameTmp);
			}
			output.writeBoolean(this.isActive);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ToggleUsernameIsActive toggleUsernameIsActive = (ToggleUsernameIsActive) o;
			if (this.username != toggleUsernameIsActive.username) {
				return false;
			}
			if (this.isActive != toggleUsernameIsActive.isActive) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.isActive);
			result = result * 31 + (this.username == null ? 0 : this.username.hashCode());
			return result;
		}
	}

	/**
	 * Changes the owner of a chat. The current user must be a current owner
	 * of the chat. Use the method canTransferOwnership to check whether the
	 * ownership can be transferred from the current session. Available only
	 * for supergroups and channel chats.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class TransferChatOwnership extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * Identifier of the user to which transfer the ownership. The ownership can&#039;t be transferred to a bot or to a deleted user.
		**/
		public long userId;

		/**
		 * The 2-step verification password of the current user.
		**/
		public String password;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2006977043;

		/**
		 * Changes the owner of a chat. The current user must be a current owner of the chat. Use the method canTransferOwnership to check whether the ownership can be transferred from the current session. Available only for supergroups and channel chats.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public TransferChatOwnership() {}

		/**
		 * Changes the owner of a chat. The current user must be a current owner of the chat. Use the method canTransferOwnership to check whether the ownership can be transferred from the current session. Available only for supergroups and channel chats.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param userId Identifier of the user to which transfer the ownership. The ownership can&#039;t be transferred to a bot or to a deleted user.
		 * @param password The 2-step verification password of the current user.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public TransferChatOwnership(long chatId, long userId, String password) {
			this.chatId = chatId;
			this.userId = userId;
			this.password = password;
		}

		/**
		 * Changes the owner of a chat. The current user must be a current owner of the chat. Use the method canTransferOwnership to check whether the ownership can be transferred from the current session. Available only for supergroups and channel chats.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TransferChatOwnership(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.userId = input.readLong();
			if (input.readBoolean()) {
				byte[] passwordTmp = new byte[input.readInt()];
				input.readFully(passwordTmp);
				this.password = new String(passwordTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TransferChatOwnership.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TransferChatOwnership.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.userId);
			if (this.password == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] passwordTmp = this.password.getBytes(StandardCharsets.UTF_8);
				output.writeInt(passwordTmp.length);
				output.write(passwordTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			TransferChatOwnership transferChatOwnership = (TransferChatOwnership) o;
			if (this.chatId != transferChatOwnership.chatId) {
				return false;
			}
			if (this.userId != transferChatOwnership.userId) {
				return false;
			}
			if (this.password != transferChatOwnership.password) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.password == null ? 0 : this.password.hashCode());
			return result;
		}
	}

	/**
	 * Extracts text or caption of the given message and translates it to
	 * the given language. If the current user is a Telegram Premium user,
	 * then text formatting is preserved.
	 * <p> Returns {@link FormattedText FormattedText} </p>
	**/
	public static final class TranslateMessageText extends Function<FormattedText> {


		/**
		 * Identifier of the chat to which the message belongs.
		**/
		public long chatId;

		/**
		 * Identifier of the message.
		**/
		public long messageId;

		/**
		 * Language code of the language to which the message is translated. Must be one of &quot;af&quot;, &quot;sq&quot;, &quot;am&quot;, &quot;ar&quot;, &quot;hy&quot;, &quot;az&quot;, &quot;eu&quot;, &quot;be&quot;, &quot;bn&quot;, &quot;bs&quot;, &quot;bg&quot;, &quot;ca&quot;, &quot;ceb&quot;, &quot;zh-CN&quot;, &quot;zh&quot;, &quot;zh-Hans&quot;, &quot;zh-TW&quot;, &quot;zh-Hant&quot;, &quot;co&quot;, &quot;hr&quot;, &quot;cs&quot;, &quot;da&quot;, &quot;nl&quot;, &quot;en&quot;, &quot;eo&quot;, &quot;et&quot;, &quot;fi&quot;, &quot;fr&quot;, &quot;fy&quot;, &quot;gl&quot;, &quot;ka&quot;, &quot;de&quot;, &quot;el&quot;, &quot;gu&quot;, &quot;ht&quot;, &quot;ha&quot;, &quot;haw&quot;, &quot;he&quot;, &quot;iw&quot;, &quot;hi&quot;, &quot;hmn&quot;, &quot;hu&quot;, &quot;is&quot;, &quot;ig&quot;, &quot;id&quot;, &quot;in&quot;, &quot;ga&quot;, &quot;it&quot;, &quot;ja&quot;, &quot;jv&quot;, &quot;kn&quot;, &quot;kk&quot;, &quot;km&quot;, &quot;rw&quot;, &quot;ko&quot;, &quot;ku&quot;, &quot;ky&quot;, &quot;lo&quot;, &quot;la&quot;, &quot;lv&quot;, &quot;lt&quot;, &quot;lb&quot;, &quot;mk&quot;, &quot;mg&quot;, &quot;ms&quot;, &quot;ml&quot;, &quot;mt&quot;, &quot;mi&quot;, &quot;mr&quot;, &quot;mn&quot;, &quot;my&quot;, &quot;ne&quot;, &quot;no&quot;, &quot;ny&quot;, &quot;or&quot;, &quot;ps&quot;, &quot;fa&quot;, &quot;pl&quot;, &quot;pt&quot;, &quot;pa&quot;, &quot;ro&quot;, &quot;ru&quot;, &quot;sm&quot;, &quot;gd&quot;, &quot;sr&quot;, &quot;st&quot;, &quot;sn&quot;, &quot;sd&quot;, &quot;si&quot;, &quot;sk&quot;, &quot;sl&quot;, &quot;so&quot;, &quot;es&quot;, &quot;su&quot;, &quot;sw&quot;, &quot;sv&quot;, &quot;tl&quot;, &quot;tg&quot;, &quot;ta&quot;, &quot;tt&quot;, &quot;te&quot;, &quot;th&quot;, &quot;tr&quot;, &quot;tk&quot;, &quot;uk&quot;, &quot;ur&quot;, &quot;ug&quot;, &quot;uz&quot;, &quot;vi&quot;, &quot;cy&quot;, &quot;xh&quot;, &quot;yi&quot;, &quot;ji&quot;, &quot;yo&quot;, &quot;zu&quot;.
		**/
		public String toLanguageCode;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 1405427410;

		/**
		 * Extracts text or caption of the given message and translates it to the given language. If the current user is a Telegram Premium user, then text formatting is preserved.
		 *
		 * <p> Returns {@link FormattedText FormattedText} </p>
		**/
		public TranslateMessageText() {}

		/**
		 * Extracts text or caption of the given message and translates it to the given language. If the current user is a Telegram Premium user, then text formatting is preserved.
		 *
		 * <p> Returns {@link FormattedText FormattedText} </p>
		 *
		 * @param chatId Identifier of the chat to which the message belongs.
		 * @param messageId Identifier of the message.
		 * @param toLanguageCode Language code of the language to which the message is translated. Must be one of &quot;af&quot;, &quot;sq&quot;, &quot;am&quot;, &quot;ar&quot;, &quot;hy&quot;, &quot;az&quot;, &quot;eu&quot;, &quot;be&quot;, &quot;bn&quot;, &quot;bs&quot;, &quot;bg&quot;, &quot;ca&quot;, &quot;ceb&quot;, &quot;zh-CN&quot;, &quot;zh&quot;, &quot;zh-Hans&quot;, &quot;zh-TW&quot;, &quot;zh-Hant&quot;, &quot;co&quot;, &quot;hr&quot;, &quot;cs&quot;, &quot;da&quot;, &quot;nl&quot;, &quot;en&quot;, &quot;eo&quot;, &quot;et&quot;, &quot;fi&quot;, &quot;fr&quot;, &quot;fy&quot;, &quot;gl&quot;, &quot;ka&quot;, &quot;de&quot;, &quot;el&quot;, &quot;gu&quot;, &quot;ht&quot;, &quot;ha&quot;, &quot;haw&quot;, &quot;he&quot;, &quot;iw&quot;, &quot;hi&quot;, &quot;hmn&quot;, &quot;hu&quot;, &quot;is&quot;, &quot;ig&quot;, &quot;id&quot;, &quot;in&quot;, &quot;ga&quot;, &quot;it&quot;, &quot;ja&quot;, &quot;jv&quot;, &quot;kn&quot;, &quot;kk&quot;, &quot;km&quot;, &quot;rw&quot;, &quot;ko&quot;, &quot;ku&quot;, &quot;ky&quot;, &quot;lo&quot;, &quot;la&quot;, &quot;lv&quot;, &quot;lt&quot;, &quot;lb&quot;, &quot;mk&quot;, &quot;mg&quot;, &quot;ms&quot;, &quot;ml&quot;, &quot;mt&quot;, &quot;mi&quot;, &quot;mr&quot;, &quot;mn&quot;, &quot;my&quot;, &quot;ne&quot;, &quot;no&quot;, &quot;ny&quot;, &quot;or&quot;, &quot;ps&quot;, &quot;fa&quot;, &quot;pl&quot;, &quot;pt&quot;, &quot;pa&quot;, &quot;ro&quot;, &quot;ru&quot;, &quot;sm&quot;, &quot;gd&quot;, &quot;sr&quot;, &quot;st&quot;, &quot;sn&quot;, &quot;sd&quot;, &quot;si&quot;, &quot;sk&quot;, &quot;sl&quot;, &quot;so&quot;, &quot;es&quot;, &quot;su&quot;, &quot;sw&quot;, &quot;sv&quot;, &quot;tl&quot;, &quot;tg&quot;, &quot;ta&quot;, &quot;tt&quot;, &quot;te&quot;, &quot;th&quot;, &quot;tr&quot;, &quot;tk&quot;, &quot;uk&quot;, &quot;ur&quot;, &quot;ug&quot;, &quot;uz&quot;, &quot;vi&quot;, &quot;cy&quot;, &quot;xh&quot;, &quot;yi&quot;, &quot;ji&quot;, &quot;yo&quot;, &quot;zu&quot;.
		 *
		 * <p> Returns {@link FormattedText FormattedText} </p>
		**/
		public TranslateMessageText(long chatId, long messageId, String toLanguageCode) {
			this.chatId = chatId;
			this.messageId = messageId;
			this.toLanguageCode = toLanguageCode;
		}

		/**
		 * Extracts text or caption of the given message and translates it to the given language. If the current user is a Telegram Premium user, then text formatting is preserved.
		 *
		 * <p> Returns {@link FormattedText FormattedText} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TranslateMessageText(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
			if (input.readBoolean()) {
				byte[] toLanguageCodeTmp = new byte[input.readInt()];
				input.readFully(toLanguageCodeTmp);
				this.toLanguageCode = new String(toLanguageCodeTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TranslateMessageText.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TranslateMessageText.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
			if (this.toLanguageCode == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] toLanguageCodeTmp = this.toLanguageCode.getBytes(StandardCharsets.UTF_8);
				output.writeInt(toLanguageCodeTmp.length);
				output.write(toLanguageCodeTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			TranslateMessageText translateMessageText = (TranslateMessageText) o;
			if (this.chatId != translateMessageText.chatId) {
				return false;
			}
			if (this.messageId != translateMessageText.messageId) {
				return false;
			}
			if (this.toLanguageCode != translateMessageText.toLanguageCode) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (this.toLanguageCode == null ? 0 : this.toLanguageCode.hashCode());
			return result;
		}
	}

	/**
	 * Translates a text to the given language. If the current user is a
	 * Telegram Premium user, then text formatting is preserved.
	 * <p> Returns {@link FormattedText FormattedText} </p>
	**/
	public static final class TranslateText extends Function<FormattedText> {


		/**
		 * Text to translate.
		**/
		public FormattedText text;

		/**
		 * Language code of the language to which the message is translated. Must be one of &quot;af&quot;, &quot;sq&quot;, &quot;am&quot;, &quot;ar&quot;, &quot;hy&quot;, &quot;az&quot;, &quot;eu&quot;, &quot;be&quot;, &quot;bn&quot;, &quot;bs&quot;, &quot;bg&quot;, &quot;ca&quot;, &quot;ceb&quot;, &quot;zh-CN&quot;, &quot;zh&quot;, &quot;zh-Hans&quot;, &quot;zh-TW&quot;, &quot;zh-Hant&quot;, &quot;co&quot;, &quot;hr&quot;, &quot;cs&quot;, &quot;da&quot;, &quot;nl&quot;, &quot;en&quot;, &quot;eo&quot;, &quot;et&quot;, &quot;fi&quot;, &quot;fr&quot;, &quot;fy&quot;, &quot;gl&quot;, &quot;ka&quot;, &quot;de&quot;, &quot;el&quot;, &quot;gu&quot;, &quot;ht&quot;, &quot;ha&quot;, &quot;haw&quot;, &quot;he&quot;, &quot;iw&quot;, &quot;hi&quot;, &quot;hmn&quot;, &quot;hu&quot;, &quot;is&quot;, &quot;ig&quot;, &quot;id&quot;, &quot;in&quot;, &quot;ga&quot;, &quot;it&quot;, &quot;ja&quot;, &quot;jv&quot;, &quot;kn&quot;, &quot;kk&quot;, &quot;km&quot;, &quot;rw&quot;, &quot;ko&quot;, &quot;ku&quot;, &quot;ky&quot;, &quot;lo&quot;, &quot;la&quot;, &quot;lv&quot;, &quot;lt&quot;, &quot;lb&quot;, &quot;mk&quot;, &quot;mg&quot;, &quot;ms&quot;, &quot;ml&quot;, &quot;mt&quot;, &quot;mi&quot;, &quot;mr&quot;, &quot;mn&quot;, &quot;my&quot;, &quot;ne&quot;, &quot;no&quot;, &quot;ny&quot;, &quot;or&quot;, &quot;ps&quot;, &quot;fa&quot;, &quot;pl&quot;, &quot;pt&quot;, &quot;pa&quot;, &quot;ro&quot;, &quot;ru&quot;, &quot;sm&quot;, &quot;gd&quot;, &quot;sr&quot;, &quot;st&quot;, &quot;sn&quot;, &quot;sd&quot;, &quot;si&quot;, &quot;sk&quot;, &quot;sl&quot;, &quot;so&quot;, &quot;es&quot;, &quot;su&quot;, &quot;sw&quot;, &quot;sv&quot;, &quot;tl&quot;, &quot;tg&quot;, &quot;ta&quot;, &quot;tt&quot;, &quot;te&quot;, &quot;th&quot;, &quot;tr&quot;, &quot;tk&quot;, &quot;uk&quot;, &quot;ur&quot;, &quot;ug&quot;, &quot;uz&quot;, &quot;vi&quot;, &quot;cy&quot;, &quot;xh&quot;, &quot;yi&quot;, &quot;ji&quot;, &quot;yo&quot;, &quot;zu&quot;.
		**/
		public String toLanguageCode;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 623011058;

		/**
		 * Translates a text to the given language. If the current user is a Telegram Premium user, then text formatting is preserved.
		 *
		 * <p> Returns {@link FormattedText FormattedText} </p>
		**/
		public TranslateText() {}

		/**
		 * Translates a text to the given language. If the current user is a Telegram Premium user, then text formatting is preserved.
		 *
		 * <p> Returns {@link FormattedText FormattedText} </p>
		 *
		 * @param text Text to translate.
		 * @param toLanguageCode Language code of the language to which the message is translated. Must be one of &quot;af&quot;, &quot;sq&quot;, &quot;am&quot;, &quot;ar&quot;, &quot;hy&quot;, &quot;az&quot;, &quot;eu&quot;, &quot;be&quot;, &quot;bn&quot;, &quot;bs&quot;, &quot;bg&quot;, &quot;ca&quot;, &quot;ceb&quot;, &quot;zh-CN&quot;, &quot;zh&quot;, &quot;zh-Hans&quot;, &quot;zh-TW&quot;, &quot;zh-Hant&quot;, &quot;co&quot;, &quot;hr&quot;, &quot;cs&quot;, &quot;da&quot;, &quot;nl&quot;, &quot;en&quot;, &quot;eo&quot;, &quot;et&quot;, &quot;fi&quot;, &quot;fr&quot;, &quot;fy&quot;, &quot;gl&quot;, &quot;ka&quot;, &quot;de&quot;, &quot;el&quot;, &quot;gu&quot;, &quot;ht&quot;, &quot;ha&quot;, &quot;haw&quot;, &quot;he&quot;, &quot;iw&quot;, &quot;hi&quot;, &quot;hmn&quot;, &quot;hu&quot;, &quot;is&quot;, &quot;ig&quot;, &quot;id&quot;, &quot;in&quot;, &quot;ga&quot;, &quot;it&quot;, &quot;ja&quot;, &quot;jv&quot;, &quot;kn&quot;, &quot;kk&quot;, &quot;km&quot;, &quot;rw&quot;, &quot;ko&quot;, &quot;ku&quot;, &quot;ky&quot;, &quot;lo&quot;, &quot;la&quot;, &quot;lv&quot;, &quot;lt&quot;, &quot;lb&quot;, &quot;mk&quot;, &quot;mg&quot;, &quot;ms&quot;, &quot;ml&quot;, &quot;mt&quot;, &quot;mi&quot;, &quot;mr&quot;, &quot;mn&quot;, &quot;my&quot;, &quot;ne&quot;, &quot;no&quot;, &quot;ny&quot;, &quot;or&quot;, &quot;ps&quot;, &quot;fa&quot;, &quot;pl&quot;, &quot;pt&quot;, &quot;pa&quot;, &quot;ro&quot;, &quot;ru&quot;, &quot;sm&quot;, &quot;gd&quot;, &quot;sr&quot;, &quot;st&quot;, &quot;sn&quot;, &quot;sd&quot;, &quot;si&quot;, &quot;sk&quot;, &quot;sl&quot;, &quot;so&quot;, &quot;es&quot;, &quot;su&quot;, &quot;sw&quot;, &quot;sv&quot;, &quot;tl&quot;, &quot;tg&quot;, &quot;ta&quot;, &quot;tt&quot;, &quot;te&quot;, &quot;th&quot;, &quot;tr&quot;, &quot;tk&quot;, &quot;uk&quot;, &quot;ur&quot;, &quot;ug&quot;, &quot;uz&quot;, &quot;vi&quot;, &quot;cy&quot;, &quot;xh&quot;, &quot;yi&quot;, &quot;ji&quot;, &quot;yo&quot;, &quot;zu&quot;.
		 *
		 * <p> Returns {@link FormattedText FormattedText} </p>
		**/
		public TranslateText(FormattedText text, String toLanguageCode) {
			this.text = text;
			this.toLanguageCode = toLanguageCode;
		}

		/**
		 * Translates a text to the given language. If the current user is a Telegram Premium user, then text formatting is preserved.
		 *
		 * <p> Returns {@link FormattedText FormattedText} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public TranslateText(DataInput input) throws IOException {
			if (input.readBoolean()) {
				if (FormattedText.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.text = new FormattedText(input);
			}
			if (input.readBoolean()) {
				byte[] toLanguageCodeTmp = new byte[input.readInt()];
				input.readFully(toLanguageCodeTmp);
				this.toLanguageCode = new String(toLanguageCodeTmp, StandardCharsets.UTF_8);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return TranslateText.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(TranslateText.CONSTRUCTOR);
			if (this.text == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.text.serialize(output);
			}
			if (this.toLanguageCode == null) {
				output.writeBoolean(false);
							} else {
				output.writeBoolean(true);
				byte[] toLanguageCodeTmp = this.toLanguageCode.getBytes(StandardCharsets.UTF_8);
				output.writeInt(toLanguageCodeTmp.length);
				output.write(toLanguageCodeTmp);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			TranslateText translateText = (TranslateText) o;
			if (!Objects.equals(this.text, translateText.text)) {
				return false;
			}
			if (this.toLanguageCode != translateText.toLanguageCode) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = this.text == null ? 0 : this.text.hashCode();
			result = result * 31 + (this.toLanguageCode == null ? 0 : this.toLanguageCode.hashCode());
			return result;
		}
	}

	/**
	 * Removes all pinned messages from a chat; requires canPinMessages
	 * rights in the group or canEditMessages rights in the channel.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class UnpinAllChatMessages extends Function<Ok> {


		/**
		 * Identifier of the chat.
		**/
		public long chatId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1437805385;

		/**
		 * Removes all pinned messages from a chat; requires canPinMessages rights in the group or canEditMessages rights in the channel.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public UnpinAllChatMessages() {}

		/**
		 * Removes all pinned messages from a chat; requires canPinMessages rights in the group or canEditMessages rights in the channel.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Identifier of the chat.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public UnpinAllChatMessages(long chatId) {
			this.chatId = chatId;
		}

		/**
		 * Removes all pinned messages from a chat; requires canPinMessages rights in the group or canEditMessages rights in the channel.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UnpinAllChatMessages(DataInput input) throws IOException {
			this.chatId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UnpinAllChatMessages.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UnpinAllChatMessages.CONSTRUCTOR);
			output.writeLong(this.chatId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UnpinAllChatMessages unpinAllChatMessages = (UnpinAllChatMessages) o;
			if (this.chatId != unpinAllChatMessages.chatId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.chatId);
		}
	}

	/**
	 * Removes all pinned messages from a forum topic; requires
	 * canPinMessages rights in the supergroup.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class UnpinAllMessageThreadMessages extends Function<Ok> {


		/**
		 * Identifier of the chat.
		**/
		public long chatId;

		/**
		 * Message thread identifier in which messages will be unpinned.
		**/
		public long messageThreadId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1211719936;

		/**
		 * Removes all pinned messages from a forum topic; requires canPinMessages rights in the supergroup.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public UnpinAllMessageThreadMessages() {}

		/**
		 * Removes all pinned messages from a forum topic; requires canPinMessages rights in the supergroup.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Identifier of the chat.
		 * @param messageThreadId Message thread identifier in which messages will be unpinned.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public UnpinAllMessageThreadMessages(long chatId, long messageThreadId) {
			this.chatId = chatId;
			this.messageThreadId = messageThreadId;
		}

		/**
		 * Removes all pinned messages from a forum topic; requires canPinMessages rights in the supergroup.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UnpinAllMessageThreadMessages(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageThreadId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UnpinAllMessageThreadMessages.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UnpinAllMessageThreadMessages.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageThreadId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UnpinAllMessageThreadMessages unpinAllMessageThreadMessages = (UnpinAllMessageThreadMessages) o;
			if (this.chatId != unpinAllMessageThreadMessages.chatId) {
				return false;
			}
			if (this.messageThreadId != unpinAllMessageThreadMessages.messageThreadId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Removes a pinned message from a chat; requires canPinMessages rights
	 * in the group or canEditMessages rights in the channel.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class UnpinChatMessage extends Function<Ok> {


		/**
		 * Identifier of the chat.
		**/
		public long chatId;

		/**
		 * Identifier of the removed pinned message.
		**/
		public long messageId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 2065448670;

		/**
		 * Removes a pinned message from a chat; requires canPinMessages rights in the group or canEditMessages rights in the channel.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public UnpinChatMessage() {}

		/**
		 * Removes a pinned message from a chat; requires canPinMessages rights in the group or canEditMessages rights in the channel.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Identifier of the chat.
		 * @param messageId Identifier of the removed pinned message.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public UnpinChatMessage(long chatId, long messageId) {
			this.chatId = chatId;
			this.messageId = messageId;
		}

		/**
		 * Removes a pinned message from a chat; requires canPinMessages rights in the group or canEditMessages rights in the channel.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UnpinChatMessage(DataInput input) throws IOException {
			this.chatId = input.readLong();
			this.messageId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UnpinChatMessage.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UnpinChatMessage.CONSTRUCTOR);
			output.writeLong(this.chatId);
			output.writeLong(this.messageId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UnpinChatMessage unpinChatMessage = (UnpinChatMessage) o;
			if (this.chatId != unpinChatMessage.chatId) {
				return false;
			}
			if (this.messageId != unpinChatMessage.messageId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			return result;
		}
	}

	/**
	 * Creates a new supergroup from an existing basic group and sends a
	 * corresponding messageChatUpgradeTo and messageChatUpgradeFrom;
	 * requires creator privileges. Deactivates the original basic group.
	 * <p> Returns {@link Chat Chat} </p>
	**/
	public static final class UpgradeBasicGroupChatToSupergroupChat extends Function<Chat> {


		/**
		 * Identifier of the chat to upgrade.
		**/
		public long chatId;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 300488122;

		/**
		 * Creates a new supergroup from an existing basic group and sends a corresponding messageChatUpgradeTo and messageChatUpgradeFrom; requires creator privileges. Deactivates the original basic group.
		 *
		 * <p> Returns {@link Chat Chat} </p>
		**/
		public UpgradeBasicGroupChatToSupergroupChat() {}

		/**
		 * Creates a new supergroup from an existing basic group and sends a corresponding messageChatUpgradeTo and messageChatUpgradeFrom; requires creator privileges. Deactivates the original basic group.
		 *
		 * <p> Returns {@link Chat Chat} </p>
		 *
		 * @param chatId Identifier of the chat to upgrade.
		 *
		 * <p> Returns {@link Chat Chat} </p>
		**/
		public UpgradeBasicGroupChatToSupergroupChat(long chatId) {
			this.chatId = chatId;
		}

		/**
		 * Creates a new supergroup from an existing basic group and sends a corresponding messageChatUpgradeTo and messageChatUpgradeFrom; requires creator privileges. Deactivates the original basic group.
		 *
		 * <p> Returns {@link Chat Chat} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UpgradeBasicGroupChatToSupergroupChat(DataInput input) throws IOException {
			this.chatId = input.readLong();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UpgradeBasicGroupChatToSupergroupChat.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UpgradeBasicGroupChatToSupergroupChat.CONSTRUCTOR);
			output.writeLong(this.chatId);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UpgradeBasicGroupChatToSupergroupChat upgradeBasicGroupChatToSupergroupChat = (UpgradeBasicGroupChatToSupergroupChat) o;
			if (this.chatId != upgradeBasicGroupChatToSupergroupChat.chatId) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Long.hashCode(this.chatId);
		}
	}

	/**
	 * Uploads a file with a sticker; returns the uploaded file.
	 * <p> Returns {@link File File} </p>
	**/
	public static final class UploadStickerFile extends Function<File> {


		/**
		 * Sticker file owner; ignored for regular users.
		**/
		public long userId;

		/**
		 * Sticker format.
		**/
		public StickerFormat stickerFormat;

		/**
		 * File file to upload; must fit in a 512x512 square. For WEBP stickers the file must be in WEBP or PNG format, which will be converted to WEBP server-side. See https://core.telegram.org/animated_stickers#technical-requirements for technical requirements.
		**/
		public InputFile sticker;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 647385283;

		/**
		 * Uploads a file with a sticker; returns the uploaded file.
		 *
		 * <p> Returns {@link File File} </p>
		**/
		public UploadStickerFile() {}

		/**
		 * Uploads a file with a sticker; returns the uploaded file.
		 *
		 * <p> Returns {@link File File} </p>
		 *
		 * @param userId Sticker file owner; ignored for regular users.
		 * @param stickerFormat Sticker format.
		 * @param sticker File file to upload; must fit in a 512x512 square. For WEBP stickers the file must be in WEBP or PNG format, which will be converted to WEBP server-side. See https://core.telegram.org/animated_stickers#technical-requirements for technical requirements.
		 *
		 * <p> Returns {@link File File} </p>
		**/
		public UploadStickerFile(long userId, StickerFormat stickerFormat, InputFile sticker) {
			this.userId = userId;
			this.stickerFormat = stickerFormat;
			this.sticker = sticker;
		}

		/**
		 * Uploads a file with a sticker; returns the uploaded file.
		 *
		 * <p> Returns {@link File File} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public UploadStickerFile(DataInput input) throws IOException {
			this.userId = input.readLong();
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case StickerFormatWebp.CONSTRUCTOR: this.stickerFormat = new StickerFormatWebp(input); break;
					case StickerFormatTgs.CONSTRUCTOR: this.stickerFormat = new StickerFormatTgs(input); break;
					case StickerFormatWebm.CONSTRUCTOR: this.stickerFormat = new StickerFormatWebm(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputFileId.CONSTRUCTOR: this.sticker = new InputFileId(input); break;
					case InputFileRemote.CONSTRUCTOR: this.sticker = new InputFileRemote(input); break;
					case InputFileLocal.CONSTRUCTOR: this.sticker = new InputFileLocal(input); break;
					case InputFileGenerated.CONSTRUCTOR: this.sticker = new InputFileGenerated(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return UploadStickerFile.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(UploadStickerFile.CONSTRUCTOR);
			output.writeLong(this.userId);
			if (this.stickerFormat == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.stickerFormat.serialize(output);
			}
			if (this.sticker == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.sticker.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			UploadStickerFile uploadStickerFile = (UploadStickerFile) o;
			if (this.userId != uploadStickerFile.userId) {
				return false;
			}
			if (!Objects.equals(this.stickerFormat, uploadStickerFile.stickerFormat)) {
				return false;
			}
			if (!Objects.equals(this.sticker, uploadStickerFile.sticker)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.userId);
			result = result * 31 + (this.stickerFormat == null ? 0 : this.stickerFormat.hashCode());
			result = result * 31 + (this.sticker == null ? 0 : this.sticker.hashCode());
			return result;
		}
	}

	/**
	 * Validates the order information provided by a user and returns the
	 * available shipping options for a flexible invoice.
	 * <p> Returns {@link ValidatedOrderInfo ValidatedOrderInfo} </p>
	**/
	public static final class ValidateOrderInfo extends Function<ValidatedOrderInfo> {


		/**
		 * The invoice.
		**/
		public InputInvoice inputInvoice;

		/**
		 * The order information, provided by the user; pass null if empty.
		**/
		public OrderInfo orderInfo;

		/**
		 * Pass true to save the order information.
		**/
		public boolean allowSave;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -1248305201;

		/**
		 * Validates the order information provided by a user and returns the available shipping options for a flexible invoice.
		 *
		 * <p> Returns {@link ValidatedOrderInfo ValidatedOrderInfo} </p>
		**/
		public ValidateOrderInfo() {}

		/**
		 * Validates the order information provided by a user and returns the available shipping options for a flexible invoice.
		 *
		 * <p> Returns {@link ValidatedOrderInfo ValidatedOrderInfo} </p>
		 *
		 * @param inputInvoice The invoice.
		 * @param orderInfo The order information, provided by the user; pass null if empty.
		 * @param allowSave Pass true to save the order information.
		 *
		 * <p> Returns {@link ValidatedOrderInfo ValidatedOrderInfo} </p>
		**/
		public ValidateOrderInfo(InputInvoice inputInvoice,
				OrderInfo orderInfo,
				boolean allowSave) {
			this.inputInvoice = inputInvoice;
			this.orderInfo = orderInfo;
			this.allowSave = allowSave;
		}

		/**
		 * Validates the order information provided by a user and returns the available shipping options for a flexible invoice.
		 *
		 * <p> Returns {@link ValidatedOrderInfo ValidatedOrderInfo} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ValidateOrderInfo(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case InputInvoiceMessage.CONSTRUCTOR: this.inputInvoice = new InputInvoiceMessage(input); break;
					case InputInvoiceName.CONSTRUCTOR: this.inputInvoice = new InputInvoiceName(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			if (input.readBoolean()) {
				if (OrderInfo.CONSTRUCTOR != input.readInt()) {
					throw new UnsupportedOperationException();
				}
				this.orderInfo = new OrderInfo(input);
			}
			this.allowSave = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ValidateOrderInfo.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ValidateOrderInfo.CONSTRUCTOR);
			if (this.inputInvoice == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.inputInvoice.serialize(output);
			}
			if (this.orderInfo == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.orderInfo.serialize(output);
			}
			output.writeBoolean(this.allowSave);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ValidateOrderInfo validateOrderInfo = (ValidateOrderInfo) o;
			if (!Objects.equals(this.inputInvoice, validateOrderInfo.inputInvoice)) {
				return false;
			}
			if (!Objects.equals(this.orderInfo, validateOrderInfo.orderInfo)) {
				return false;
			}
			if (this.allowSave != validateOrderInfo.allowSave) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Boolean.hashCode(this.allowSave);
			result = result * 31 + (this.inputInvoice == null ? 0 : this.inputInvoice.hashCode());
			result = result * 31 + (this.orderInfo == null ? 0 : this.orderInfo.hashCode());
			return result;
		}
	}

	/**
	 * Informs TDLib that messages are being viewed by the user. Sponsored
	 * messages must be marked as viewed only when the entire text of the
	 * message is shown on the screen (excluding the button). Many useful
	 * activities depend on whether the messages are currently being viewed
	 * or not (e.g., marking messages as read, incrementing a view counter,
	 * updating a view counter, removing deleted messages in supergroups and
	 * channels).
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ViewMessages extends Function<Ok> {


		/**
		 * Chat identifier.
		**/
		public long chatId;

		/**
		 * The identifiers of the messages being viewed.
		**/
		public long[] messageIds;

		/**
		 * Source of the message view; pass null to guess the source based on chat open state.
		**/
		public MessageSource source;

		/**
		 * Pass true to mark as read the specified messages even the chat is closed.
		**/
		public boolean forceRead;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 960236656;

		/**
		 * Informs TDLib that messages are being viewed by the user. Sponsored messages must be marked as viewed only when the entire text of the message is shown on the screen (excluding the button). Many useful activities depend on whether the messages are currently being viewed or not (e.g., marking messages as read, incrementing a view counter, updating a view counter, removing deleted messages in supergroups and channels).
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ViewMessages() {}

		/**
		 * Informs TDLib that messages are being viewed by the user. Sponsored messages must be marked as viewed only when the entire text of the message is shown on the screen (excluding the button). Many useful activities depend on whether the messages are currently being viewed or not (e.g., marking messages as read, incrementing a view counter, updating a view counter, removing deleted messages in supergroups and channels).
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param chatId Chat identifier.
		 * @param messageIds The identifiers of the messages being viewed.
		 * @param source Source of the message view; pass null to guess the source based on chat open state.
		 * @param forceRead Pass true to mark as read the specified messages even the chat is closed.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ViewMessages(long chatId,
				long[] messageIds,
				MessageSource source,
				boolean forceRead) {
			this.chatId = chatId;
			this.messageIds = messageIds;
			this.source = source;
			this.forceRead = forceRead;
		}

		/**
		 * Informs TDLib that messages are being viewed by the user. Sponsored messages must be marked as viewed only when the entire text of the message is shown on the screen (excluding the button). Many useful activities depend on whether the messages are currently being viewed or not (e.g., marking messages as read, incrementing a view counter, updating a view counter, removing deleted messages in supergroups and channels).
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ViewMessages(DataInput input) throws IOException {
			this.chatId = input.readLong();
			if (input.readBoolean()) {
				this.messageIds = new long[input.readInt()];
				for (int i = 0; i < this.messageIds.length; i++) {
					this.messageIds[i] = input.readLong();
				}
			}
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case MessageSourceChatHistory.CONSTRUCTOR: this.source = new MessageSourceChatHistory(input); break;
					case MessageSourceMessageThreadHistory.CONSTRUCTOR: this.source = new MessageSourceMessageThreadHistory(input); break;
					case MessageSourceForumTopicHistory.CONSTRUCTOR: this.source = new MessageSourceForumTopicHistory(input); break;
					case MessageSourceHistoryPreview.CONSTRUCTOR: this.source = new MessageSourceHistoryPreview(input); break;
					case MessageSourceChatList.CONSTRUCTOR: this.source = new MessageSourceChatList(input); break;
					case MessageSourceSearch.CONSTRUCTOR: this.source = new MessageSourceSearch(input); break;
					case MessageSourceChatEventLog.CONSTRUCTOR: this.source = new MessageSourceChatEventLog(input); break;
					case MessageSourceNotification.CONSTRUCTOR: this.source = new MessageSourceNotification(input); break;
					case MessageSourceOther.CONSTRUCTOR: this.source = new MessageSourceOther(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
			this.forceRead = input.readBoolean();
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ViewMessages.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ViewMessages.CONSTRUCTOR);
			output.writeLong(this.chatId);
			if (this.messageIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.messageIds.length);
				for (int i = 0; i < this.messageIds.length; i++) {
					output.writeLong(this.messageIds[i]);
				}
			}
			if (this.source == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.source.serialize(output);
			}
			output.writeBoolean(this.forceRead);
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ViewMessages viewMessages = (ViewMessages) o;
			if (this.chatId != viewMessages.chatId) {
				return false;
			}
			if (!Arrays.equals(this.messageIds, viewMessages.messageIds)) {
				return false;
			}
			if (!Objects.equals(this.source, viewMessages.source)) {
				return false;
			}
			if (this.forceRead != viewMessages.forceRead) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.chatId);
			result = result * 31 + (Arrays.hashCode(this.messageIds));
			result = result * 31 + (this.source == null ? 0 : this.source.hashCode());
			return result;
		}
	}

	/**
	 * Informs TDLib that the user viewed detailed information about a
	 * Premium feature on the Premium features screen.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ViewPremiumFeature extends Function<Ok> {


		/**
		 * The viewed premium feature.
		**/
		public PremiumFeature feature;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 192950706;

		/**
		 * Informs TDLib that the user viewed detailed information about a Premium feature on the Premium features screen.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ViewPremiumFeature() {}

		/**
		 * Informs TDLib that the user viewed detailed information about a Premium feature on the Premium features screen.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param feature The viewed premium feature.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ViewPremiumFeature(PremiumFeature feature) {
			this.feature = feature;
		}

		/**
		 * Informs TDLib that the user viewed detailed information about a Premium feature on the Premium features screen.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ViewPremiumFeature(DataInput input) throws IOException {
			if (input.readBoolean()) {
				switch(input.readInt()) {
					case PremiumFeatureIncreasedLimits.CONSTRUCTOR: this.feature = new PremiumFeatureIncreasedLimits(input); break;
					case PremiumFeatureIncreasedUploadFileSize.CONSTRUCTOR: this.feature = new PremiumFeatureIncreasedUploadFileSize(input); break;
					case PremiumFeatureImprovedDownloadSpeed.CONSTRUCTOR: this.feature = new PremiumFeatureImprovedDownloadSpeed(input); break;
					case PremiumFeatureVoiceRecognition.CONSTRUCTOR: this.feature = new PremiumFeatureVoiceRecognition(input); break;
					case PremiumFeatureDisabledAds.CONSTRUCTOR: this.feature = new PremiumFeatureDisabledAds(input); break;
					case PremiumFeatureUniqueReactions.CONSTRUCTOR: this.feature = new PremiumFeatureUniqueReactions(input); break;
					case PremiumFeatureUniqueStickers.CONSTRUCTOR: this.feature = new PremiumFeatureUniqueStickers(input); break;
					case PremiumFeatureCustomEmoji.CONSTRUCTOR: this.feature = new PremiumFeatureCustomEmoji(input); break;
					case PremiumFeatureAdvancedChatManagement.CONSTRUCTOR: this.feature = new PremiumFeatureAdvancedChatManagement(input); break;
					case PremiumFeatureProfileBadge.CONSTRUCTOR: this.feature = new PremiumFeatureProfileBadge(input); break;
					case PremiumFeatureEmojiStatus.CONSTRUCTOR: this.feature = new PremiumFeatureEmojiStatus(input); break;
					case PremiumFeatureAnimatedProfilePhoto.CONSTRUCTOR: this.feature = new PremiumFeatureAnimatedProfilePhoto(input); break;
					case PremiumFeatureForumTopicIcon.CONSTRUCTOR: this.feature = new PremiumFeatureForumTopicIcon(input); break;
					case PremiumFeatureAppIcons.CONSTRUCTOR: this.feature = new PremiumFeatureAppIcons(input); break;
					case PremiumFeatureRealTimeChatTranslation.CONSTRUCTOR: this.feature = new PremiumFeatureRealTimeChatTranslation(input); break;
					default: {
						throw new UnsupportedOperationException();
					}
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ViewPremiumFeature.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ViewPremiumFeature.CONSTRUCTOR);
			if (this.feature == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				this.feature.serialize(output);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ViewPremiumFeature viewPremiumFeature = (ViewPremiumFeature) o;
			if (!Objects.equals(this.feature, viewPremiumFeature.feature)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return this.feature == null ? 0 : this.feature.hashCode();
		}
	}

	/**
	 * Informs the server that some trending sticker sets have been viewed
	 * by the user.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class ViewTrendingStickerSets extends Function<Ok> {


		/**
		 * Identifiers of viewed trending sticker sets.
		**/
		public long[] stickerSetIds;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = -952416520;

		/**
		 * Informs the server that some trending sticker sets have been viewed by the user.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ViewTrendingStickerSets() {}

		/**
		 * Informs the server that some trending sticker sets have been viewed by the user.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param stickerSetIds Identifiers of viewed trending sticker sets.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public ViewTrendingStickerSets(long[] stickerSetIds) {
			this.stickerSetIds = stickerSetIds;
		}

		/**
		 * Informs the server that some trending sticker sets have been viewed by the user.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public ViewTrendingStickerSets(DataInput input) throws IOException {
			if (input.readBoolean()) {
				this.stickerSetIds = new long[input.readInt()];
				for (int i = 0; i < this.stickerSetIds.length; i++) {
					this.stickerSetIds[i] = input.readLong();
				}
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return ViewTrendingStickerSets.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(ViewTrendingStickerSets.CONSTRUCTOR);
			if (this.stickerSetIds == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.stickerSetIds.length);
				for (int i = 0; i < this.stickerSetIds.length; i++) {
					output.writeLong(this.stickerSetIds[i]);
				}
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			ViewTrendingStickerSets viewTrendingStickerSets = (ViewTrendingStickerSets) o;
			if (!Arrays.equals(this.stickerSetIds, viewTrendingStickerSets.stickerSetIds)) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			return Arrays.hashCode(this.stickerSetIds);
		}
	}

	/**
	 * Writes a part of a generated file. This method is intended to be used
	 * only if the application has no direct access to TDLib&#039;s file
	 * system, because it is usually slower than a direct write to the
	 * destination file.
	 * <p> Returns {@link Ok Ok} </p>
	**/
	public static final class WriteGeneratedFilePart extends Function<Ok> {


		/**
		 * The identifier of the generation process.
		**/
		public long generationId;

		/**
		 * The offset from which to write the data to the file.
		**/
		public long offset;

		/**
		 * The data to write.
		**/
		public byte[] data;

		/**
		 * Identifier uniquely determining type of the object.
		**/
		public static final int CONSTRUCTOR = 214474389;

		/**
		 * Writes a part of a generated file. This method is intended to be used only if the application has no direct access to TDLib&#039;s file system, because it is usually slower than a direct write to the destination file.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public WriteGeneratedFilePart() {}

		/**
		 * Writes a part of a generated file. This method is intended to be used only if the application has no direct access to TDLib&#039;s file system, because it is usually slower than a direct write to the destination file.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param generationId The identifier of the generation process.
		 * @param offset The offset from which to write the data to the file.
		 * @param data The data to write.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		**/
		public WriteGeneratedFilePart(long generationId, long offset, byte[] data) {
			this.generationId = generationId;
			this.offset = offset;
			this.data = data;
		}

		/**
		 * Writes a part of a generated file. This method is intended to be used only if the application has no direct access to TDLib&#039;s file system, because it is usually slower than a direct write to the destination file.
		 *
		 * <p> Returns {@link Ok Ok} </p>
		 *
		 * @param input Serialized input
		 * @throws IOException the deserialization failed
		**/
		public WriteGeneratedFilePart(DataInput input) throws IOException {
			this.generationId = input.readLong();
			this.offset = input.readLong();
			if (input.readBoolean()) {
				this.data = new byte[input.readInt()];
				input.readFully(this.data);
			}
		}

		/**
		 * @return this.CONSTRUCTOR
		**/
		public int getConstructor() {
			return WriteGeneratedFilePart.CONSTRUCTOR;
		}

		/**
		 * Serialize the TDLib class
		 * @param output output data stream
		 * @throws IOException the serialization failed
		**/
		public void serialize(DataOutput output) throws IOException {
			output.writeInt(WriteGeneratedFilePart.CONSTRUCTOR);
			output.writeLong(this.generationId);
			output.writeLong(this.offset);
			if (this.data == null) {
				output.writeBoolean(false);
			} else {
				output.writeBoolean(true);
				output.writeInt(this.data.length);
				output.write(this.data);
			}
		}


		public boolean equals(java.lang.Object o) {
			if (this == o) {
				return true;
			}
			if (o == null || getClass() != o.getClass()) {
				return false;
			}
			WriteGeneratedFilePart writeGeneratedFilePart = (WriteGeneratedFilePart) o;
			if (this.generationId != writeGeneratedFilePart.generationId) {
				return false;
			}
			if (this.offset != writeGeneratedFilePart.offset) {
				return false;
			}
			if (this.data != writeGeneratedFilePart.data) {
				return false;
			}
			return true;
		}

		public int hashCode() {
			int result = Long.hashCode(this.generationId);
			result = result * 31 + (Arrays.hashCode(this.data));
			return result;
		}
	}

}