diff --git a/telegrambots-chat-session-bot/README.md b/telegrambots-chat-session-bot/README.md
new file mode 100644
index 00000000..e6237511
--- /dev/null
+++ b/telegrambots-chat-session-bot/README.md
@@ -0,0 +1,55 @@
+
+
+[![Build Status](https://travis-ci.org/rubenlagus/TelegramBots.svg?branch=master)](https://travis-ci.org/rubenlagus/TelegramBots)
+[![Jitpack](https://jitpack.io/v/rubenlagus/TelegramBots.svg)](https://jitpack.io/#rubenlagus/TelegramBots)
+[![Telegram](http://trellobot.doomdns.org/telegrambadge.svg)](https://telegram.me/JavaBotsApi)
+
+
+
+Usage
+-----
+
+**Maven**
+
+```xml
+
+ org.telegram
+ telegrambots-chat-session-bot
+ 4.0.0
+
+```
+
+Motivation
+----------
+Implementation of bot dialogs require saving some data about current state of conversation.
+That brings us to idea of chat session management.
+
+How to use
+----------
+`Chat session bot` was implemented by using [`Shiro Apache`](https://shiro.apache.org/) session manager.
+That allow to manage and store sessions.
+
+
+To create default Long Polling Session Bot with in-memory store,
+you need simply implement `TelegramLongPollingSessionBot`
+```java
+public class ExampleBotWithSession extends TelegramLongPollingSessionBot {
+
+ @Override
+ public void onUpdateReceived(Update update, Optional optionalSession) {
+ //Do some action with update and session
+ }
+
+ @Override
+ public String getBotUsername() {
+ return "ExampleBotWithSessionBot";
+ }
+
+ @Override
+ public String getBotToken() {
+ return "1234";
+ }
+}
+```
+
+Where session is implementation of `org.apache.shiro.session.Session`
\ No newline at end of file
diff --git a/telegrambots-chat-session-bot/pom.xml b/telegrambots-chat-session-bot/pom.xml
new file mode 100644
index 00000000..23050544
--- /dev/null
+++ b/telegrambots-chat-session-bot/pom.xml
@@ -0,0 +1,254 @@
+
+
+ 4.0.0
+ org.telegram
+ telegrambots-chat-session-bot
+ 4.0.0
+ jar
+
+ Telegram Bots Chat Session Bot
+ https://github.com/rubenlagus/TelegramBots
+ Telegram bot with chat session support
+
+
+ https://github.com/rubenlagus/TelegramBots/issues
+ GitHub Issues
+
+
+
+ https://github.com/rubenlagus/TelegramBots
+ scm:git:git://github.com/rubenlagus/TelegramBots.git
+ scm:git:git@github.com:rubenlagus/TelegramBots.git
+
+
+
+ https://travis-ci.org/rubenlagus/TelegramBots
+ Travis
+
+
+
+
+ rberlopez@gmail.com
+ Ruben Bermudez
+ https://github.com/rubenlagus
+ rubenlagus
+
+
+ bochkarevei@gmail.com
+ Egor Bochkarev
+ https://github.com/EgorBochkarev
+ EgorBochkarev
+
+
+
+
+
+ MIT License
+ http://www.opensource.org/licenses/mit-license.php
+ repo
+
+
+
+
+
+ ossrh
+ https://oss.sonatype.org/content/repositories/snapshots
+
+
+ ossrh
+ https://oss.sonatype.org/service/local/staging/deploy/maven2/
+
+
+
+
+ UTF-8
+ UTF-8
+ 4.0.0
+ 1.4.0
+
+
+
+
+
+ org.telegram
+ telegrambots
+ ${bots.version}
+
+
+
+
+ org.apache.shiro
+ shiro-core
+ ${shiro.version}
+
+
+
+ org.mockito
+ mockito-all
+ 2.0.2-beta
+ test
+
+
+ junit
+ junit
+ 4.11
+ test
+
+
+
+
+ ${project.basedir}/target
+ ${project.build.directory}/classes
+ ${project.artifactId}-${project.version}
+ ${project.build.directory}/test-classes
+ ${project.basedir}/src/main/java
+
+
+ org.apache.maven.plugins
+ maven-gpg-plugin
+ 1.5
+
+
+ sign-artifacts
+ verify
+
+ sign
+
+
+
+
+
+ org.sonatype.plugins
+ nexus-staging-maven-plugin
+ 1.6.3
+ true
+
+ ossrh
+ https://oss.sonatype.org/
+ true
+
+
+
+ maven-clean-plugin
+ 3.0.0
+
+
+ clean-project
+ clean
+
+ clean
+
+
+
+
+
+ maven-assembly-plugin
+ 2.6
+
+
+ jar-with-dependencies
+
+
+
+
+ make-assembly
+ package
+
+ single
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+ 3.0.0
+
+
+
+ jar
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 2.10.3
+
+
+
+ jar
+
+
+ -Xdoclint:none
+
+
+
+
+
+ org.jacoco
+ jacoco-maven-plugin
+ 0.7.7.201606060606
+
+
+
+ prepare-agent
+
+
+
+ report
+ test
+
+ report
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-enforcer-plugin
+ 1.4.1
+
+
+ enforce-versions
+
+ enforce
+
+
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-dependency-plugin
+ 2.4
+
+
+ copy
+ package
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ 1.8
+ 1.8
+ UTF-8
+
+
+
+
+
+
\ No newline at end of file
diff --git a/telegrambots-chat-session-bot/src/main/java/org/telegram/telegrambots/session/ChatIdConverter.java b/telegrambots-chat-session-bot/src/main/java/org/telegram/telegrambots/session/ChatIdConverter.java
new file mode 100644
index 00000000..43d6ab33
--- /dev/null
+++ b/telegrambots-chat-session-bot/src/main/java/org/telegram/telegrambots/session/ChatIdConverter.java
@@ -0,0 +1,10 @@
+package org.telegram.telegrambots.session;
+
+import org.apache.shiro.session.mgt.SessionKey;
+import org.apache.shiro.session.mgt.eis.SessionIdGenerator;
+
+import java.io.Serializable;
+
+public interface ChatIdConverter extends SessionKey, SessionIdGenerator {
+ void setSessionId(Serializable sessionId);
+}
\ No newline at end of file
diff --git a/telegrambots-chat-session-bot/src/main/java/org/telegram/telegrambots/session/DefaultChatIdConverter.java b/telegrambots-chat-session-bot/src/main/java/org/telegram/telegrambots/session/DefaultChatIdConverter.java
new file mode 100644
index 00000000..5e5dd571
--- /dev/null
+++ b/telegrambots-chat-session-bot/src/main/java/org/telegram/telegrambots/session/DefaultChatIdConverter.java
@@ -0,0 +1,34 @@
+package org.telegram.telegrambots.session;
+
+import org.apache.shiro.session.Session;
+
+import java.io.Serializable;
+
+@SuppressWarnings({"unused", "WeakerAccess"})
+public class DefaultChatIdConverter implements ChatIdConverter {
+ private long sessionId;
+
+ public DefaultChatIdConverter() {
+ super();
+ }
+
+ public DefaultChatIdConverter(long sessionId) {
+ this();
+ this.sessionId = sessionId;
+ }
+
+ @Override
+ public void setSessionId(Serializable sessionId){
+ this.sessionId = (long) sessionId;
+ };
+
+ @Override
+ public Serializable getSessionId() {
+ return sessionId;
+ }
+
+ @Override
+ public Serializable generateId(Session session) {
+ return getSessionId();
+ }
+}
diff --git a/telegrambots-chat-session-bot/src/main/java/org/telegram/telegrambots/session/DefaultChatSessionContext.java b/telegrambots-chat-session-bot/src/main/java/org/telegram/telegrambots/session/DefaultChatSessionContext.java
new file mode 100644
index 00000000..08ef999f
--- /dev/null
+++ b/telegrambots-chat-session-bot/src/main/java/org/telegram/telegrambots/session/DefaultChatSessionContext.java
@@ -0,0 +1,37 @@
+package org.telegram.telegrambots.session;
+
+import org.apache.shiro.session.mgt.SessionContext;
+
+import java.io.Serializable;
+import java.util.HashMap;
+
+@SuppressWarnings("WeakerAccess")
+public class DefaultChatSessionContext extends HashMap implements SessionContext {
+ private long sessionId;
+ private String host;
+
+ public DefaultChatSessionContext(long sessionId, String host) {
+ this.sessionId = sessionId;
+ this.host = host;
+ }
+
+ @Override
+ public String getHost() {
+ return host;
+ }
+
+ @Override
+ public void setHost(String host) {
+ this.host = host;
+ }
+
+ @Override
+ public Serializable getSessionId() {
+ return sessionId;
+ }
+
+ @Override
+ public void setSessionId(Serializable serializable) {
+ this.sessionId = (long) serializable;
+ }
+}
diff --git a/telegrambots-chat-session-bot/src/main/java/org/telegram/telegrambots/session/TelegramLongPollingSessionBot.java b/telegrambots-chat-session-bot/src/main/java/org/telegram/telegrambots/session/TelegramLongPollingSessionBot.java
new file mode 100644
index 00000000..8182578e
--- /dev/null
+++ b/telegrambots-chat-session-bot/src/main/java/org/telegram/telegrambots/session/TelegramLongPollingSessionBot.java
@@ -0,0 +1,67 @@
+package org.telegram.telegrambots.session;
+
+import org.apache.shiro.session.Session;
+import org.apache.shiro.session.UnknownSessionException;
+import org.apache.shiro.session.mgt.DefaultSessionManager;
+import org.apache.shiro.session.mgt.SessionContext;
+import org.apache.shiro.session.mgt.eis.AbstractSessionDAO;
+import org.telegram.telegrambots.meta.api.objects.Message;
+import org.telegram.telegrambots.meta.api.objects.Update;
+import org.telegram.telegrambots.bots.TelegramLongPollingBot;
+
+import java.util.Optional;
+
+@SuppressWarnings({"WeakerAccess", "OptionalUsedAsFieldOrParameterType", "unused"})
+public abstract class TelegramLongPollingSessionBot extends TelegramLongPollingBot {
+ DefaultSessionManager sessionManager;
+
+ ChatIdConverter chatIdConverter;
+
+ public TelegramLongPollingSessionBot(){
+ this(new DefaultChatIdConverter());
+ }
+
+ public TelegramLongPollingSessionBot(ChatIdConverter chatIdConverter){
+ this.setSessionManager(new DefaultSessionManager());
+ this.setChatIdConverter(chatIdConverter);
+ AbstractSessionDAO sessionDAO = (AbstractSessionDAO) sessionManager.getSessionDAO();
+ sessionDAO.setSessionIdGenerator(chatIdConverter);
+ }
+
+ public void setSessionManager(DefaultSessionManager sessionManager) {
+ this.sessionManager = sessionManager;
+ }
+
+ public void setChatIdConverter(ChatIdConverter chatIdConverter) {
+ this.chatIdConverter = chatIdConverter;
+ }
+
+ @Override
+ public void onUpdateReceived(Update update) {
+ Optional chatSession;
+ Message message;
+ if (update.hasMessage()) {
+ message = update.getMessage();
+ } else if (update.hasCallbackQuery()) {
+ message = update.getCallbackQuery().getMessage();
+ } else {
+ chatSession = Optional.empty();
+ onUpdateReceived(update, chatSession);
+ return;
+ }
+ chatIdConverter.setSessionId(message.getChatId());
+ chatSession = this.getSession(message);
+ onUpdateReceived(update, chatSession);
+ }
+
+ public Optional getSession(Message message){
+ try {
+ return Optional.of(sessionManager.getSession(chatIdConverter));
+ } catch (UnknownSessionException e) {
+ SessionContext botSession = new DefaultChatSessionContext(message.getChatId(), message.getFrom().getUserName());
+ return Optional.of(sessionManager.start(botSession));
+ }
+ }
+
+ public abstract void onUpdateReceived(Update update, Optional botSession);
+}